BundleStore
This commit is contained in:
parent
920cba5219
commit
31924ce6d1
6 changed files with 47 additions and 25 deletions
|
@ -7,13 +7,12 @@ import androidx.annotation.NonNull;
|
||||||
import androidx.work.Worker;
|
import androidx.work.Worker;
|
||||||
import androidx.work.WorkerParameters;
|
import androidx.work.WorkerParameters;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import dagger.android.HasAndroidInjector;
|
import dagger.android.HasAndroidInjector;
|
||||||
|
import info.nightscout.androidaps.receivers.BundleStore;
|
||||||
|
|
||||||
// cannot be inner class because of needed injection
|
// cannot be inner class because of needed injection
|
||||||
public class NSClientWorker extends Worker {
|
public class NSClientWorker extends Worker {
|
||||||
|
@ -26,11 +25,13 @@ public class NSClientWorker extends Worker {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject NSClientPlugin nsClientPlugin;
|
@Inject NSClientPlugin nsClientPlugin;
|
||||||
|
@Inject BundleStore bundleStore;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public Result doWork() {
|
public Result doWork() {
|
||||||
Bundle bundle = new Gson().fromJson(getInputData().getString("data"), Bundle.class);
|
Bundle bundle = bundleStore.pickup(getInputData().getLong("storeKey", -1));
|
||||||
|
if (bundle == null) Result.failure();
|
||||||
String action = getInputData().getString("action");
|
String action = getInputData().getString("action");
|
||||||
nsClientPlugin.handleNewDataFromNSClient(action, bundle);
|
nsClientPlugin.handleNewDataFromNSClient(action, bundle);
|
||||||
return Result.success();
|
return Result.success();
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package info.nightscout.androidaps.plugins.general.smsCommunicator
|
package info.nightscout.androidaps.plugins.general.smsCommunicator
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.Bundle
|
|
||||||
import android.telephony.SmsManager
|
import android.telephony.SmsManager
|
||||||
import android.telephony.SmsMessage
|
import android.telephony.SmsMessage
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
|
@ -10,15 +9,12 @@ import androidx.preference.Preference
|
||||||
import androidx.preference.PreferenceFragmentCompat
|
import androidx.preference.PreferenceFragmentCompat
|
||||||
import androidx.work.Worker
|
import androidx.work.Worker
|
||||||
import androidx.work.WorkerParameters
|
import androidx.work.WorkerParameters
|
||||||
import com.google.gson.Gson
|
|
||||||
import dagger.android.HasAndroidInjector
|
import dagger.android.HasAndroidInjector
|
||||||
import info.nightscout.androidaps.Config
|
import info.nightscout.androidaps.Config
|
||||||
import info.nightscout.androidaps.Constants
|
import info.nightscout.androidaps.Constants
|
||||||
import info.nightscout.androidaps.MainApp
|
|
||||||
import info.nightscout.androidaps.R
|
import info.nightscout.androidaps.R
|
||||||
import info.nightscout.androidaps.data.DetailedBolusInfo
|
import info.nightscout.androidaps.data.DetailedBolusInfo
|
||||||
import info.nightscout.androidaps.data.Profile
|
import info.nightscout.androidaps.data.Profile
|
||||||
import info.nightscout.androidaps.db.BgReading
|
|
||||||
import info.nightscout.androidaps.db.Source
|
import info.nightscout.androidaps.db.Source
|
||||||
import info.nightscout.androidaps.db.TempTarget
|
import info.nightscout.androidaps.db.TempTarget
|
||||||
import info.nightscout.androidaps.events.EventPreferenceChange
|
import info.nightscout.androidaps.events.EventPreferenceChange
|
||||||
|
@ -29,7 +25,6 @@ import info.nightscout.androidaps.logging.LTag
|
||||||
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
|
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
||||||
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
||||||
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
|
|
||||||
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart
|
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart
|
||||||
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification
|
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification
|
||||||
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification
|
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification
|
||||||
|
@ -37,9 +32,9 @@ import info.nightscout.androidaps.plugins.general.smsCommunicator.events.EventSm
|
||||||
import info.nightscout.androidaps.plugins.general.smsCommunicator.otp.OneTimePassword
|
import info.nightscout.androidaps.plugins.general.smsCommunicator.otp.OneTimePassword
|
||||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus
|
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus
|
||||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
|
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
|
||||||
import info.nightscout.androidaps.plugins.source.PoctechPlugin
|
|
||||||
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
|
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
|
||||||
import info.nightscout.androidaps.queue.Callback
|
import info.nightscout.androidaps.queue.Callback
|
||||||
|
import info.nightscout.androidaps.receivers.BundleStore
|
||||||
import info.nightscout.androidaps.utils.*
|
import info.nightscout.androidaps.utils.*
|
||||||
import info.nightscout.androidaps.utils.extensions.plusAssign
|
import info.nightscout.androidaps.utils.extensions.plusAssign
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
|
@ -48,8 +43,6 @@ import info.nightscout.androidaps.utils.textValidator.ValidatingEditTextPreferen
|
||||||
import io.reactivex.disposables.CompositeDisposable
|
import io.reactivex.disposables.CompositeDisposable
|
||||||
import io.reactivex.schedulers.Schedulers
|
import io.reactivex.schedulers.Schedulers
|
||||||
import org.apache.commons.lang3.StringUtils
|
import org.apache.commons.lang3.StringUtils
|
||||||
import org.json.JSONArray
|
|
||||||
import org.json.JSONException
|
|
||||||
import java.text.Normalizer
|
import java.text.Normalizer
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
@ -161,7 +154,6 @@ class SmsCommunicatorPlugin @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// cannot be inner class because of needed injection
|
// cannot be inner class because of needed injection
|
||||||
class SmsCommunicatorWorker(
|
class SmsCommunicatorWorker(
|
||||||
context: Context,
|
context: Context,
|
||||||
|
@ -169,13 +161,15 @@ class SmsCommunicatorPlugin @Inject constructor(
|
||||||
) : Worker(context, params) {
|
) : Worker(context, params) {
|
||||||
|
|
||||||
@Inject lateinit var smsCommunicatorPlugin: SmsCommunicatorPlugin
|
@Inject lateinit var smsCommunicatorPlugin: SmsCommunicatorPlugin
|
||||||
|
@Inject lateinit var bundleStore: BundleStore
|
||||||
|
|
||||||
init {
|
init {
|
||||||
(context.applicationContext as HasAndroidInjector).androidInjector().inject(this)
|
(context.applicationContext as HasAndroidInjector).androidInjector().inject(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun doWork(): Result {
|
override fun doWork(): Result {
|
||||||
val bundle = Gson().fromJson(inputData.getString("data"), Bundle::class.java)
|
val bundle = bundleStore.pickup(inputData.getLong("storeKey", -1))
|
||||||
|
?: return Result.failure()
|
||||||
val format = bundle.getString("format") ?: return Result.failure()
|
val format = bundle.getString("format") ?: return Result.failure()
|
||||||
val pdus = bundle["pdus"] as Array<*>
|
val pdus = bundle["pdus"] as Array<*>
|
||||||
for (pdu in pdus) {
|
for (pdu in pdus) {
|
||||||
|
@ -185,6 +179,7 @@ class SmsCommunicatorPlugin @Inject constructor(
|
||||||
return Result.success()
|
return Result.success()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun processSettings(ev: EventPreferenceChange?) {
|
private fun processSettings(ev: EventPreferenceChange?) {
|
||||||
if (ev == null || ev.isChanged(resourceHelper, R.string.key_smscommunicator_allowednumbers)) {
|
if (ev == null || ev.isChanged(resourceHelper, R.string.key_smscommunicator_allowednumbers)) {
|
||||||
val settings = sp.getString(R.string.key_smscommunicator_allowednumbers, "")
|
val settings = sp.getString(R.string.key_smscommunicator_allowednumbers, "")
|
||||||
|
|
|
@ -3,11 +3,9 @@ package info.nightscout.androidaps.plugins.source
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.os.Bundle
|
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.work.Worker
|
import androidx.work.Worker
|
||||||
import androidx.work.WorkerParameters
|
import androidx.work.WorkerParameters
|
||||||
import com.google.gson.Gson
|
|
||||||
import dagger.android.HasAndroidInjector
|
import dagger.android.HasAndroidInjector
|
||||||
import info.nightscout.androidaps.Config
|
import info.nightscout.androidaps.Config
|
||||||
import info.nightscout.androidaps.Constants
|
import info.nightscout.androidaps.Constants
|
||||||
|
@ -23,6 +21,7 @@ import info.nightscout.androidaps.interfaces.PluginDescription
|
||||||
import info.nightscout.androidaps.interfaces.PluginType
|
import info.nightscout.androidaps.interfaces.PluginType
|
||||||
import info.nightscout.androidaps.logging.AAPSLogger
|
import info.nightscout.androidaps.logging.AAPSLogger
|
||||||
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
|
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
|
||||||
|
import info.nightscout.androidaps.receivers.BundleStore
|
||||||
import info.nightscout.androidaps.utils.DateUtil
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
import info.nightscout.androidaps.utils.T
|
import info.nightscout.androidaps.utils.T
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
|
@ -87,6 +86,7 @@ class DexcomPlugin @Inject constructor(
|
||||||
@Inject lateinit var dexcomPlugin: DexcomPlugin
|
@Inject lateinit var dexcomPlugin: DexcomPlugin
|
||||||
@Inject lateinit var nsUpload: NSUpload
|
@Inject lateinit var nsUpload: NSUpload
|
||||||
@Inject lateinit var sp: SP
|
@Inject lateinit var sp: SP
|
||||||
|
@Inject lateinit var bundleStore: BundleStore
|
||||||
|
|
||||||
init {
|
init {
|
||||||
(context.applicationContext as HasAndroidInjector).androidInjector().inject(this)
|
(context.applicationContext as HasAndroidInjector).androidInjector().inject(this)
|
||||||
|
@ -94,8 +94,8 @@ class DexcomPlugin @Inject constructor(
|
||||||
|
|
||||||
override fun doWork(): Result {
|
override fun doWork(): Result {
|
||||||
if (!dexcomPlugin.isEnabled(PluginType.BGSOURCE)) return Result.failure()
|
if (!dexcomPlugin.isEnabled(PluginType.BGSOURCE)) return Result.failure()
|
||||||
val action = inputData.getString("action")
|
val bundle = bundleStore.pickup(inputData.getLong("storeKey", -1))
|
||||||
val bundle = Gson().fromJson(inputData.getString("data"), Bundle::class.java)
|
?: return Result.failure()
|
||||||
try {
|
try {
|
||||||
val sensorType = bundle.getString("sensorType") ?: ""
|
val sensorType = bundle.getString("sensorType") ?: ""
|
||||||
val glucoseValues = bundle.getBundle("glucoseValues") ?: return Result.failure()
|
val glucoseValues = bundle.getBundle("glucoseValues") ?: return Result.failure()
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
package info.nightscout.androidaps.plugins.source
|
package info.nightscout.androidaps.plugins.source
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.Bundle
|
|
||||||
import androidx.work.Worker
|
import androidx.work.Worker
|
||||||
import androidx.work.WorkerParameters
|
import androidx.work.WorkerParameters
|
||||||
import com.google.gson.Gson
|
|
||||||
import dagger.android.HasAndroidInjector
|
import dagger.android.HasAndroidInjector
|
||||||
import info.nightscout.androidaps.Constants
|
import info.nightscout.androidaps.Constants
|
||||||
import info.nightscout.androidaps.MainApp
|
import info.nightscout.androidaps.MainApp
|
||||||
|
@ -18,6 +16,7 @@ import info.nightscout.androidaps.interfaces.PluginType
|
||||||
import info.nightscout.androidaps.logging.AAPSLogger
|
import info.nightscout.androidaps.logging.AAPSLogger
|
||||||
import info.nightscout.androidaps.logging.LTag
|
import info.nightscout.androidaps.logging.LTag
|
||||||
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
|
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
|
||||||
|
import info.nightscout.androidaps.receivers.BundleStore
|
||||||
import info.nightscout.androidaps.utils.DateUtil
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
||||||
|
@ -56,6 +55,7 @@ class EversensePlugin @Inject constructor(
|
||||||
@Inject lateinit var sp: SP
|
@Inject lateinit var sp: SP
|
||||||
@Inject lateinit var nsUpload: NSUpload
|
@Inject lateinit var nsUpload: NSUpload
|
||||||
@Inject lateinit var dateUtil: DateUtil
|
@Inject lateinit var dateUtil: DateUtil
|
||||||
|
@Inject lateinit var bundleStore: BundleStore
|
||||||
|
|
||||||
init {
|
init {
|
||||||
(context.applicationContext as HasAndroidInjector).androidInjector().inject(this)
|
(context.applicationContext as HasAndroidInjector).androidInjector().inject(this)
|
||||||
|
@ -63,7 +63,8 @@ class EversensePlugin @Inject constructor(
|
||||||
|
|
||||||
override fun doWork(): Result {
|
override fun doWork(): Result {
|
||||||
if (!eversensePlugin.isEnabled(PluginType.BGSOURCE)) return Result.failure()
|
if (!eversensePlugin.isEnabled(PluginType.BGSOURCE)) return Result.failure()
|
||||||
val bundle = Gson().fromJson(inputData.getString("data"), Bundle::class.java)
|
val bundle = bundleStore.pickup(inputData.getLong("storeKey", -1))
|
||||||
|
?: return Result.failure()
|
||||||
if (bundle.containsKey("currentCalibrationPhase")) aapsLogger.debug(LTag.BGSOURCE, "currentCalibrationPhase: " + bundle.getString("currentCalibrationPhase"))
|
if (bundle.containsKey("currentCalibrationPhase")) aapsLogger.debug(LTag.BGSOURCE, "currentCalibrationPhase: " + bundle.getString("currentCalibrationPhase"))
|
||||||
if (bundle.containsKey("placementModeInProgress")) aapsLogger.debug(LTag.BGSOURCE, "placementModeInProgress: " + bundle.getBoolean("placementModeInProgress"))
|
if (bundle.containsKey("placementModeInProgress")) aapsLogger.debug(LTag.BGSOURCE, "placementModeInProgress: " + bundle.getBoolean("placementModeInProgress"))
|
||||||
if (bundle.containsKey("glucoseLevel")) aapsLogger.debug(LTag.BGSOURCE, "glucoseLevel: " + bundle.getInt("glucoseLevel"))
|
if (bundle.containsKey("glucoseLevel")) aapsLogger.debug(LTag.BGSOURCE, "glucoseLevel: " + bundle.getInt("glucoseLevel"))
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
package info.nightscout.androidaps.receivers
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
class BundleStore @Inject constructor() {
|
||||||
|
private val store = HashMap<Long, Bundle>()
|
||||||
|
private var counter = 0L
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
|
fun store(bundle: Bundle) : Long {
|
||||||
|
store.put(counter, bundle)
|
||||||
|
return counter++
|
||||||
|
}
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
|
fun pickup(key: Long) : Bundle? {
|
||||||
|
val bundle = store[key]
|
||||||
|
store.remove(key)
|
||||||
|
return bundle
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,7 +7,6 @@ import androidx.work.Data
|
||||||
import androidx.work.ExistingWorkPolicy
|
import androidx.work.ExistingWorkPolicy
|
||||||
import androidx.work.OneTimeWorkRequest
|
import androidx.work.OneTimeWorkRequest
|
||||||
import androidx.work.WorkManager
|
import androidx.work.WorkManager
|
||||||
import com.google.gson.Gson
|
|
||||||
import dagger.android.DaggerBroadcastReceiver
|
import dagger.android.DaggerBroadcastReceiver
|
||||||
import info.nightscout.androidaps.logging.AAPSLogger
|
import info.nightscout.androidaps.logging.AAPSLogger
|
||||||
import info.nightscout.androidaps.logging.BundleLogger
|
import info.nightscout.androidaps.logging.BundleLogger
|
||||||
|
@ -21,11 +20,13 @@ import info.nightscout.androidaps.utils.extensions.copyDouble
|
||||||
import info.nightscout.androidaps.utils.extensions.copyInt
|
import info.nightscout.androidaps.utils.extensions.copyInt
|
||||||
import info.nightscout.androidaps.utils.extensions.copyLong
|
import info.nightscout.androidaps.utils.extensions.copyLong
|
||||||
import info.nightscout.androidaps.utils.extensions.copyString
|
import info.nightscout.androidaps.utils.extensions.copyString
|
||||||
|
import org.json.JSONObject
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
open class DataReceiver : DaggerBroadcastReceiver() {
|
open class DataReceiver : DaggerBroadcastReceiver() {
|
||||||
|
|
||||||
@Inject lateinit var aapsLogger: AAPSLogger
|
@Inject lateinit var aapsLogger: AAPSLogger
|
||||||
|
@Inject lateinit var bundleStore: BundleStore
|
||||||
|
|
||||||
private val jobGroupName = "data"
|
private val jobGroupName = "data"
|
||||||
|
|
||||||
|
@ -84,19 +85,19 @@ open class DataReceiver : DaggerBroadcastReceiver() {
|
||||||
Telephony.Sms.Intents.SMS_RECEIVED_ACTION ->
|
Telephony.Sms.Intents.SMS_RECEIVED_ACTION ->
|
||||||
OneTimeWorkRequest.Builder(SmsCommunicatorPlugin.SmsCommunicatorWorker::class.java)
|
OneTimeWorkRequest.Builder(SmsCommunicatorPlugin.SmsCommunicatorWorker::class.java)
|
||||||
.setInputData(Data.Builder().also {
|
.setInputData(Data.Builder().also {
|
||||||
it.putString("data", Gson().toJson(bundle))
|
it.putLong("storeKey", bundleStore.store(bundle))
|
||||||
it.putString("action", intent.action)
|
it.putString("action", intent.action)
|
||||||
}.build()).build()
|
}.build()).build()
|
||||||
Intents.EVERSENSE_BG ->
|
Intents.EVERSENSE_BG ->
|
||||||
OneTimeWorkRequest.Builder(EversensePlugin.EversenseWorker::class.java)
|
OneTimeWorkRequest.Builder(EversensePlugin.EversenseWorker::class.java)
|
||||||
.setInputData(Data.Builder().also {
|
.setInputData(Data.Builder().also {
|
||||||
it.putString("data", Gson().toJson(bundle))
|
it.putLong("storeKey", bundleStore.store(bundle))
|
||||||
it.putString("action", intent.action)
|
it.putString("action", intent.action)
|
||||||
}.build()).build()
|
}.build()).build()
|
||||||
Intents.DEXCOM_BG ->
|
Intents.DEXCOM_BG ->
|
||||||
OneTimeWorkRequest.Builder(DexcomPlugin.DexcomWorker::class.java)
|
OneTimeWorkRequest.Builder(DexcomPlugin.DexcomWorker::class.java)
|
||||||
.setInputData(Data.Builder().also {
|
.setInputData(Data.Builder().also {
|
||||||
it.putString("data", Gson().toJson(bundle))
|
it.putLong("storeKey", bundleStore.store(bundle))
|
||||||
it.putString("action", intent.action)
|
it.putString("action", intent.action)
|
||||||
}.build()).build()
|
}.build()).build()
|
||||||
Intents.ACTION_NEW_TREATMENT,
|
Intents.ACTION_NEW_TREATMENT,
|
||||||
|
@ -106,7 +107,7 @@ open class DataReceiver : DaggerBroadcastReceiver() {
|
||||||
Intents.ACTION_NEW_MBG ->
|
Intents.ACTION_NEW_MBG ->
|
||||||
OneTimeWorkRequest.Builder(NSClientWorker::class.java)
|
OneTimeWorkRequest.Builder(NSClientWorker::class.java)
|
||||||
.setInputData(Data.Builder().also {
|
.setInputData(Data.Builder().also {
|
||||||
it.putString("data", Gson().toJson(bundle))
|
it.putLong("storeKey", bundleStore.store(bundle))
|
||||||
it.putString("action", intent.action)
|
it.putString("action", intent.action)
|
||||||
}.build()).build()
|
}.build()).build()
|
||||||
else -> null
|
else -> null
|
||||||
|
|
Loading…
Reference in a new issue