0
0
mirror of https://github.com/ankidroid/Anki-Android.git synced 2024-09-19 19:42:17 +02:00

cleanup: Hungarian Notation - all but 5 files (#15181)

* cleanup: AddContentApi - Hungarian Notation
* cleanup: SharedDecksDownloadFragment - Hungarian Notation
* cleanup: AbstractFlashcardViewer - Hungarian Notation
* cleanup: Reviewer - Hungarian Notation
* cleanup: RecursivePictureMenu - Hungarian Notation
* cleanup: FieldEditLine - Hungarian Notation
* cleanup: ActivityExportingDelegate - Hungarian Notation
* cleanup: DeckPicker - Hungarian Notation
* cleanup: MultimediaEditFieldActivity - Hungarian Notation
* cleanup: FieldControllerBase - Hungarian Notation
* cleanup: AnkiDroidJsAPI - Hungarian Notation
* cleanup: DeckAdapter - Hungarian Notation
* cleanup: Previewer - Hungarian Notation
* cleanup: CardTemplatePreviewer - Hungarian Notation
* cleanup: BasicImageFieldController - Hungarian Notation
* cleanup: AudioRecorder - Hungarian Notation
* cleanup: AppCompatPreferenceActivity - Hungarian Notation
* cleanup: AudioField - Hungarian Notation
* cleanup: Collection - Hungarian Notation
* cleanup: MultimediaEditableNote - Hungarian Notation
* cleanup: CardTemplateNotetype - Hungarian Notation
* cleanup: Card - Hungarian Notation
* cleanup: BasicTextFieldController - Hungarian Notation
This commit is contained in:
David Allison 2024-01-09 00:28:30 +00:00 committed by GitHub
parent 240d9d8f55
commit 5f2cc77db6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
33 changed files with 1020 additions and 1013 deletions

View File

@ -121,15 +121,15 @@ abstract class AbstractFlashcardViewer :
OnPageFinishedCallback,
BaseSnackbarBuilderProvider,
ChangeManager.Subscriber {
private var mTtsInitialized = false
private var mReplayOnTtsInit = false
private var mAnkiDroidJsAPI: AnkiDroidJsAPI? = null
private var ttsInitialized = false
private var replayOnTtsInit = false
private var ankiDroidJsAPI: AnkiDroidJsAPI? = null
/**
* Broadcast that informs us when the sd card is about to be unmounted
*/
private var mUnmountReceiver: BroadcastReceiver? = null
private var mTagsDialogFactory: TagsDialogFactory? = null
private var unmountReceiver: BroadcastReceiver? = null
private var tagsDialogFactory: TagsDialogFactory? = null
/**
* Variables to hold preferences
@ -138,13 +138,13 @@ abstract class AbstractFlashcardViewer :
internal var prefShowTopbar = false
protected var fullscreenMode = DEFAULT
private set
private var mRelativeButtonSize = 0
private var relativeButtonSize = 0
private var minimalClickSpeed = 0
private var mDoubleScrolling = false
private var mGesturesEnabled = false
private var mLargeAnswerButtons = false
protected var mAnswerButtonsPosition: String? = "bottom"
private var mDoubleTapTimeInterval = DEFAULT_DOUBLE_TAP_TIME_INTERVAL
private var doubleScrolling = false
private var gesturesEnabled = false
private var largeAnswerButtons = false
protected var answerButtonsPosition: String? = "bottom"
private var doubleTapTimeInterval = DEFAULT_DOUBLE_TAP_TIME_INTERVAL
// Android WebView
var automaticAnswer = AutomaticAnswer.defaultInstance(this)
@ -153,24 +153,24 @@ abstract class AbstractFlashcardViewer :
internal var typeAnswer: TypeAnswer? = null
/** Generates HTML content */
private var mHtmlGenerator: HtmlGenerator? = null
private var htmlGenerator: HtmlGenerator? = null
// Default short animation duration, provided by Android framework
private var shortAnimDuration = 0
private var mBackButtonPressedToReturn = false
private var backButtonPressedToReturn = false
// Preferences from the collection
private var mShowNextReviewTime = false
private var mIsSelecting = false
private var mInAnswer = false
private var showNextReviewTime = false
private var isSelecting = false
private var inAnswer = false
/**
* Variables to hold layout objects that we need to update or handle events for
*/
var webView: WebView? = null
private set
private var mCardFrame: FrameLayout? = null
private var mTouchLayer: FrameLayout? = null
private var cardFrame: FrameLayout? = null
private var touchLayer: FrameLayout? = null
protected var answerField: FixedEditText? = null
protected var flipCardLayout: FrameLayout? = null
private var easeButtonsLayout: LinearLayout? = null
@ -187,12 +187,12 @@ abstract class AbstractFlashcardViewer :
@KotlinCleanup("internal for AnkiDroidJsApi")
internal var easeButton4: EaseButton? = null
protected var topBarLayout: RelativeLayout? = null
private val mClipboard: ClipboardManager? = null
private var mPreviousAnswerIndicator: PreviousAnswerIndicator? = null
private val clipboard: ClipboardManager? = null
private var previousAnswerIndicator: PreviousAnswerIndicator? = null
private var mCurrentEase = 0
private var mInitialFlipCardHeight = 0
private var mButtonHeightSet = false
private var currentEase = 0
private var initialFlipCardHeight = 0
private var buttonHeightSet = false
/**
* A record of the last time the "show answer" or ease buttons were pressed. We keep track
@ -206,14 +206,14 @@ abstract class AbstractFlashcardViewer :
*/
var gestureDetector: GestureDetector? = null
private set
private lateinit var mGestureDetectorImpl: MyGestureDetector
private var mIsXScrolling = false
private var mIsYScrolling = false
private lateinit var gestureDetectorImpl: MyGestureDetector
private var isXScrolling = false
private var isYScrolling = false
/**
* Gesture Allocation
*/
protected val mGestureProcessor = GestureProcessor(this)
protected val gestureProcessor = GestureProcessor(this)
/** Handle joysticks/pedals */
// needs to be lateinit due to a reliance on Context
@ -224,36 +224,36 @@ abstract class AbstractFlashcardViewer :
private set
open val baseUrl = "http://$LOCALHOST"
open val webviewDomain = LOCALHOST
private var mViewerUrl: String? = null
private val mFadeDuration = 300
private var viewerUrl: String? = null
private val fadeDuration = 300
@VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
internal lateinit var soundPlayer: SoundPlayer
/** Reference to the parent of the cardFrame to allow regeneration of the cardFrame in case of crash */
private var mCardFrameParent: ViewGroup? = null
private var cardFrameParent: ViewGroup? = null
/** Lock to allow thread-safe regeneration of mCard */
private val mCardLock: ReadWriteLock = ReentrantReadWriteLock()
private val cardLock: ReadWriteLock = ReentrantReadWriteLock()
/** Preference: Whether the user wants press back twice to return to the main screen" */
private var mExitViaDoubleTapBack = false
private var exitViaDoubleTapBack = false
@VisibleForTesting
val mOnRenderProcessGoneDelegate = OnRenderProcessGoneDelegate(this)
protected val mTTS = TTS()
val onRenderProcessGoneDelegate = OnRenderProcessGoneDelegate(this)
protected val tts = TTS()
// ----------------------------------------------------------------------------
// LISTENERS
// ----------------------------------------------------------------------------
private val mLongClickHandler = newHandler()
private val mStartLongClickAction = Runnable { mGestureProcessor.onLongTap() }
private val longClickHandler = newHandler()
private val startLongClickAction = Runnable { gestureProcessor.onLongTap() }
// Handler for the "show answer" button
private val mFlipCardListener = View.OnClickListener {
private val flipCardListener = View.OnClickListener {
Timber.i("AbstractFlashcardViewer:: Show answer button pressed")
// Ignore what is most likely an accidental double-tap.
if (elapsedRealTime - lastClickTime < mDoubleTapTimeInterval) {
if (elapsedRealTime - lastClickTime < doubleTapTimeInterval) {
return@OnClickListener
}
lastClickTime = elapsedRealTime
@ -316,27 +316,27 @@ abstract class AbstractFlashcardViewer :
// Event handler for eases (answer buttons)
inner class SelectEaseHandler : View.OnClickListener, OnTouchListener {
private var mPrevCard: Card? = null
private var mHasBeenTouched = false
private var mTouchX = 0f
private var mTouchY = 0f
private var prevCard: Card? = null
private var hasBeenTouched = false
private var touchX = 0f
private var touchY = 0f
override fun onTouch(view: View, event: MotionEvent): Boolean {
if (event.action == MotionEvent.ACTION_DOWN) {
// Save states when button pressed
mPrevCard = currentCard
mHasBeenTouched = true
prevCard = currentCard
hasBeenTouched = true
// We will need to check if a touch is followed by a click
// Since onTouch always come before onClick, we should check if
// the touch is going to be a click by storing the start coordinates
// and comparing with the end coordinates of the touch
mTouchX = event.rawX
mTouchY = event.rawY
touchX = event.rawX
touchY = event.rawY
} else if (event.action == MotionEvent.ACTION_UP) {
val diffX = abs(event.rawX - mTouchX)
val diffY = abs(event.rawY - mTouchY)
val diffX = abs(event.rawX - touchX)
val diffY = abs(event.rawY - touchY)
// If a click is not coming then we reset the touch
if (diffX > Companion.CLICK_ACTION_THRESHOLD || diffY > Companion.CLICK_ACTION_THRESHOLD) {
mHasBeenTouched = false
hasBeenTouched = false
}
}
return false
@ -345,11 +345,11 @@ abstract class AbstractFlashcardViewer :
override fun onClick(view: View) {
// Try to perform intended action only if the button has been pressed for current card,
// or if the button was not touched,
if (mPrevCard === currentCard || !mHasBeenTouched) {
if (prevCard === currentCard || !hasBeenTouched) {
// Only perform if the click was not an accidental double-tap
if (elapsedRealTime - lastClickTime >= mDoubleTapTimeInterval) {
if (elapsedRealTime - lastClickTime >= doubleTapTimeInterval) {
// For whatever reason, performClick does not return a visual feedback anymore
if (!mHasBeenTouched) {
if (!hasBeenTouched) {
view.isPressed = true
}
lastClickTime = elapsedRealTime
@ -375,29 +375,29 @@ abstract class AbstractFlashcardViewer :
answerCard(Consts.BUTTON_FOUR)
}
else -> mCurrentEase = 0
else -> currentEase = 0
}
if (!mHasBeenTouched) {
if (!hasBeenTouched) {
view.isPressed = false
}
}
}
// We will have to reset the touch after every onClick event
// Do not return early without considering this
mHasBeenTouched = false
hasBeenTouched = false
}
}
private val mEaseHandler = SelectEaseHandler()
private val easeHandler = SelectEaseHandler()
@get:VisibleForTesting
protected open val elapsedRealTime: Long
get() = SystemClock.elapsedRealtime()
private val mGestureListener = OnTouchListener { _, event ->
private val gestureListener = OnTouchListener { _, event ->
if (gestureDetector!!.onTouchEvent(event)) {
return@OnTouchListener true
}
if (!mGestureDetectorImpl.eventCanBeSentToWebView(event)) {
if (!gestureDetectorImpl.eventCanBeSentToWebView(event)) {
return@OnTouchListener false
}
// Gesture listener is added before mCard is set
@ -419,7 +419,7 @@ abstract class AbstractFlashcardViewer :
@CheckResult
private fun <T> processCardFunction(cardFunction: Function<WebView?, T>): T {
val readLock = mCardLock.readLock()
val readLock = cardLock.readLock()
return try {
readLock.lock()
cardFunction.apply(webView)
@ -514,7 +514,7 @@ abstract class AbstractFlashcardViewer :
// ----------------------------------------------------------------------------
override fun onCreate(savedInstanceState: Bundle?) {
restorePreferences()
mTagsDialogFactory = TagsDialogFactory(this).attachToActivity<TagsDialogFactory>(this)
tagsDialogFactory = TagsDialogFactory(this).attachToActivity<TagsDialogFactory>(this)
super.onCreate(savedInstanceState)
motionEventHandler = MotionEventHandler.createInstance(this)
@ -528,9 +528,9 @@ abstract class AbstractFlashcardViewer :
delegate.isHandleNativeActionModesEnabled = true
val mainView = findViewById<View>(android.R.id.content)
initNavigationDrawer(mainView)
mPreviousAnswerIndicator = PreviousAnswerIndicator(findViewById(R.id.chosen_answer))
previousAnswerIndicator = PreviousAnswerIndicator(findViewById(R.id.chosen_answer))
shortAnimDuration = resources.getInteger(android.R.integer.config_shortAnimTime)
mGestureDetectorImpl = LinkDetectingGestureDetector()
gestureDetectorImpl = LinkDetectingGestureDetector()
TtsVoicesFieldFilter.ensureApplied()
if (!sharedPrefs().getBoolean("showDeckTitle", false)) {
supportActionBar?.setDisplayShowTitleEnabled(false)
@ -559,10 +559,10 @@ abstract class AbstractFlashcardViewer :
registerExternalStorageListener()
restoreCollectionPreferences(col)
initLayout()
mHtmlGenerator = createInstance(this, col, typeAnswer!!)
htmlGenerator = createInstance(this, col, typeAnswer!!)
// Initialize text-to-speech. This is an asynchronous operation.
mTTS.initialize(this, ReadTextListener())
tts.initialize(this, ReadTextListener())
updateActionBar()
invalidateOptionsMenu()
}
@ -586,8 +586,8 @@ abstract class AbstractFlashcardViewer :
override fun onPause() {
super.onPause()
automaticAnswer.disable()
mGestureDetectorImpl.stopShakeDetector()
mLongClickHandler.removeCallbacks(mStartLongClickAction)
gestureDetectorImpl.stopShakeDetector()
longClickHandler.removeCallbacks(startLongClickAction)
// Prevent loss of data in Cookies
CookieManager.getInstance().flush()
}
@ -595,7 +595,7 @@ abstract class AbstractFlashcardViewer :
override fun onResume() {
super.onResume()
automaticAnswer.enable()
mGestureDetectorImpl.startShakeDetector()
gestureDetectorImpl.startShakeDetector()
// Reset the activity title
updateActionBar()
selectNavigationItem(-1)
@ -627,14 +627,14 @@ abstract class AbstractFlashcardViewer :
override fun onDestroy() {
super.onDestroy()
mTTS.releaseTts(this)
if (mUnmountReceiver != null) {
unregisterReceiver(mUnmountReceiver)
tts.releaseTts(this)
if (unmountReceiver != null) {
unregisterReceiver(unmountReceiver)
}
// WebView.destroy() should be called after the end of use
// http://developer.android.com/reference/android/webkit/WebView.html#destroy()
if (mCardFrame != null) {
mCardFrame!!.removeAllViews()
if (cardFrame != null) {
cardFrame!!.removeAllViews()
}
destroyWebView(webView) // OK to do without a lock
}
@ -644,14 +644,14 @@ abstract class AbstractFlashcardViewer :
super.onBackPressed()
} else {
Timber.i("Back key pressed")
if (!mExitViaDoubleTapBack || mBackButtonPressedToReturn) {
if (!exitViaDoubleTapBack || backButtonPressedToReturn) {
closeReviewer(RESULT_DEFAULT)
} else {
showSnackbar(R.string.back_pressed_once_reviewer, Snackbar.LENGTH_SHORT)
}
mBackButtonPressedToReturn = true
backButtonPressedToReturn = true
executeFunctionWithDelay(Consts.SHORT_TOAST_DURATION) {
mBackButtonPressedToReturn = false
backButtonPressedToReturn = false
}
}
}
@ -695,14 +695,14 @@ abstract class AbstractFlashcardViewer :
private fun processHardwareButtonScroll(keyCode: Int, card: WebView?): Boolean {
if (keyCode == KeyEvent.KEYCODE_PAGE_UP) {
card!!.pageUp(false)
if (mDoubleScrolling) {
if (doubleScrolling) {
card.pageUp(false)
}
return true
}
if (keyCode == KeyEvent.KEYCODE_PAGE_DOWN) {
card!!.pageDown(false)
if (mDoubleScrolling) {
if (doubleScrolling) {
card.pageDown(false)
}
return true
@ -715,7 +715,7 @@ abstract class AbstractFlashcardViewer :
}
protected fun clipboardHasText(): Boolean {
return !getText(mClipboard).isNullOrEmpty()
return !getText(clipboard).isNullOrEmpty()
}
/**
@ -725,7 +725,7 @@ abstract class AbstractFlashcardViewer :
* @return the text in clipboard or the empty string.
*/
private fun clipboardGetText(): CharSequence {
val text = getText(mClipboard)
val text = getText(clipboard)
return text ?: ""
}
@ -779,8 +779,8 @@ abstract class AbstractFlashcardViewer :
* Show/dismiss dialog when sd card is ejected/remounted (collection is saved by SdCardReceiver)
*/
private fun registerExternalStorageListener() {
if (mUnmountReceiver == null) {
mUnmountReceiver = object : BroadcastReceiver() {
if (unmountReceiver == null) {
unmountReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (intent.action == SdCardReceiver.MEDIA_EJECT) {
finish()
@ -789,7 +789,7 @@ abstract class AbstractFlashcardViewer :
}
val iFilter = IntentFilter()
iFilter.addAction(SdCardReceiver.MEDIA_EJECT)
registerReceiver(mUnmountReceiver, iFilter)
registerReceiver(unmountReceiver, iFilter)
}
}
@ -861,18 +861,18 @@ abstract class AbstractFlashcardViewer :
open fun answerCard(@BUTTON_TYPE ease: Int) {
launchCatchingTask {
if (mInAnswer) {
if (inAnswer) {
return@launchCatchingTask
}
mIsSelecting = false
if (mPreviousAnswerIndicator == null) {
isSelecting = false
if (previousAnswerIndicator == null) {
// workaround for a broken ReviewerKeyboardInputTest
return@launchCatchingTask
}
// Temporarily sets the answer indicator dots appearing below the toolbar
mPreviousAnswerIndicator?.displayAnswerIndicator(ease)
previousAnswerIndicator?.displayAnswerIndicator(ease)
soundPlayer.stopSounds()
mCurrentEase = ease
currentEase = ease
answerCardInner(ease)
updateCardAndRedraw()
@ -890,40 +890,40 @@ abstract class AbstractFlashcardViewer :
@KotlinCleanup("Move a lot of these to onCreate()")
protected open fun initLayout() {
topBarLayout = findViewById(R.id.top_bar)
mCardFrame = findViewById(R.id.flashcard)
mCardFrameParent = mCardFrame!!.parent as ViewGroup
mTouchLayer =
findViewById<FrameLayout>(R.id.touch_layer).apply { setOnTouchListener(mGestureListener) }
mCardFrame!!.removeAllViews()
cardFrame = findViewById(R.id.flashcard)
cardFrameParent = cardFrame!!.parent as ViewGroup
touchLayer =
findViewById<FrameLayout>(R.id.touch_layer).apply { setOnTouchListener(gestureListener) }
cardFrame!!.removeAllViews()
// Initialize swipe
gestureDetector = GestureDetector(this, mGestureDetectorImpl)
gestureDetector = GestureDetector(this, gestureDetectorImpl)
easeButtonsLayout = findViewById(R.id.ease_buttons)
easeButton1 = EaseButton(
EASE_1,
findViewById(R.id.flashcard_layout_ease1),
findViewById(R.id.ease1),
findViewById(R.id.nextTime1)
).apply { setListeners(mEaseHandler) }
).apply { setListeners(easeHandler) }
easeButton2 = EaseButton(
EASE_2,
findViewById(R.id.flashcard_layout_ease2),
findViewById(R.id.ease2),
findViewById(R.id.nextTime2)
).apply { setListeners(mEaseHandler) }
).apply { setListeners(easeHandler) }
easeButton3 = EaseButton(
EASE_3,
findViewById(R.id.flashcard_layout_ease3),
findViewById(R.id.ease3),
findViewById(R.id.nextTime3)
).apply { setListeners(mEaseHandler) }
).apply { setListeners(easeHandler) }
easeButton4 = EaseButton(
EASE_4,
findViewById(R.id.flashcard_layout_ease4),
findViewById(R.id.ease4),
findViewById(R.id.nextTime4)
).apply { setListeners(mEaseHandler) }
if (!mShowNextReviewTime) {
).apply { setListeners(easeHandler) }
if (!showNextReviewTime) {
easeButton1!!.hideNextReviewTime()
easeButton2!!.hideNextReviewTime()
easeButton3!!.hideNextReviewTime()
@ -932,14 +932,14 @@ abstract class AbstractFlashcardViewer :
flipCardLayout = findViewById(R.id.flashcard_layout_flip)
flipCardLayout?.let { layout ->
if (minimalClickSpeed == 0) {
layout.setOnClickListener(mFlipCardListener)
layout.setOnClickListener(flipCardListener)
} else {
val handler = Handler(Looper.getMainLooper())
layout.setOnTouchListener { _, event ->
when (event.action) {
MotionEvent.ACTION_DOWN -> {
handler.postDelayed({
mFlipCardListener.onClick(layout)
flipCardListener.onClick(layout)
}, minimalClickSpeed.toLong())
false
}
@ -957,19 +957,19 @@ abstract class AbstractFlashcardViewer :
if (animationEnabled()) {
flipCardLayout?.setBackgroundResource(getResFromAttr(this, R.attr.hardButtonRippleRef))
}
if (!mButtonHeightSet && mRelativeButtonSize != 100) {
if (!buttonHeightSet && relativeButtonSize != 100) {
val params = flipCardLayout!!.layoutParams
params.height = params.height * mRelativeButtonSize / 100
easeButton1!!.setButtonScale(mRelativeButtonSize)
easeButton2!!.setButtonScale(mRelativeButtonSize)
easeButton3!!.setButtonScale(mRelativeButtonSize)
easeButton4!!.setButtonScale(mRelativeButtonSize)
mButtonHeightSet = true
params.height = params.height * relativeButtonSize / 100
easeButton1!!.setButtonScale(relativeButtonSize)
easeButton2!!.setButtonScale(relativeButtonSize)
easeButton3!!.setButtonScale(relativeButtonSize)
easeButton4!!.setButtonScale(relativeButtonSize)
buttonHeightSet = true
}
mInitialFlipCardHeight = flipCardLayout!!.layoutParams.height
if (mLargeAnswerButtons) {
initialFlipCardHeight = flipCardLayout!!.layoutParams.height
if (largeAnswerButtons) {
val params = flipCardLayout!!.layoutParams
params.height = mInitialFlipCardHeight * 2
params.height = initialFlipCardHeight * 2
}
answerField = findViewById(R.id.answer_field)
initControls()
@ -979,14 +979,14 @@ abstract class AbstractFlashcardViewer :
getString(R.string.answer_buttons_position_preference),
"bottom"
)
mAnswerButtonsPosition = answerButtonsPosition
this.answerButtonsPosition = answerButtonsPosition
val answerArea = findViewById<LinearLayout>(R.id.bottom_area_layout)
val answerAreaParams = answerArea.layoutParams as RelativeLayout.LayoutParams
val whiteboardContainer = findViewById<FrameLayout>(R.id.whiteboard)
val whiteboardContainerParams =
whiteboardContainer.layoutParams as RelativeLayout.LayoutParams
val flashcardContainerParams = mCardFrame!!.layoutParams as RelativeLayout.LayoutParams
val touchLayerContainerParams = mTouchLayer!!.layoutParams as RelativeLayout.LayoutParams
val flashcardContainerParams = cardFrame!!.layoutParams as RelativeLayout.LayoutParams
val touchLayerContainerParams = touchLayer!!.layoutParams as RelativeLayout.LayoutParams
when (answerButtonsPosition) {
"top" -> {
whiteboardContainerParams.addRule(RelativeLayout.BELOW, R.id.bottom_area_layout)
@ -1021,8 +1021,8 @@ abstract class AbstractFlashcardViewer :
}
answerArea.layoutParams = answerAreaParams
whiteboardContainer.layoutParams = whiteboardContainerParams
mCardFrame!!.layoutParams = flashcardContainerParams
mTouchLayer!!.layoutParams = touchLayerContainerParams
cardFrame!!.layoutParams = flashcardContainerParams
touchLayer!!.layoutParams = touchLayerContainerParams
}
protected open fun createWebView(): WebView {
@ -1101,13 +1101,13 @@ abstract class AbstractFlashcardViewer :
}
protected fun shouldShowNextReviewTime(): Boolean {
return mShowNextReviewTime
return showNextReviewTime
}
protected open fun displayAnswerBottomBar() {
flipCardLayout!!.isClickable = false
easeButtonsLayout!!.visibility = View.VISIBLE
if (mLargeAnswerButtons) {
if (largeAnswerButtons) {
easeButtonsLayout!!.orientation = LinearLayout.VERTICAL
easeButtonsLayout!!.removeAllViewsInLayout()
easeButton1!!.detachFromParent()
@ -1175,12 +1175,12 @@ abstract class AbstractFlashcardViewer :
}
protected open fun switchTopBarVisibility(visible: Int) {
mPreviousAnswerIndicator!!.setVisibility(visible)
previousAnswerIndicator!!.setVisibility(visible)
}
protected open fun initControls() {
mCardFrame!!.visibility = View.VISIBLE
mPreviousAnswerIndicator!!.setVisibility(View.VISIBLE)
cardFrame!!.visibility = View.VISIBLE
previousAnswerIndicator!!.setVisibility(View.VISIBLE)
flipCardLayout!!.visibility = View.VISIBLE
answerField!!.visibility = if (typeAnswer!!.validForEditText()) View.VISIBLE else View.GONE
answerField!!.setOnEditorActionListener { _, actionId: Int, _ ->
@ -1207,17 +1207,17 @@ abstract class AbstractFlashcardViewer :
// mDeckFilename = preferences.getString("deckFilename", "");
minimalClickSpeed = preferences.getInt("showCardAnswerButtonTime", 0)
fullscreenMode = fromPreference(preferences)
mRelativeButtonSize = preferences.getInt("answerButtonSize", 100)
mTTS.enabled = preferences.getBoolean("tts", false)
mDoubleScrolling = preferences.getBoolean("double_scrolling", false)
relativeButtonSize = preferences.getInt("answerButtonSize", 100)
tts.enabled = preferences.getBoolean("tts", false)
doubleScrolling = preferences.getBoolean("double_scrolling", false)
prefShowTopbar = preferences.getBoolean("showTopbar", true)
mLargeAnswerButtons = preferences.getBoolean("showLargeAnswerButtons", false)
mDoubleTapTimeInterval =
largeAnswerButtons = preferences.getBoolean("showLargeAnswerButtons", false)
doubleTapTimeInterval =
preferences.getInt(DOUBLE_TAP_TIME_INTERVAL, DEFAULT_DOUBLE_TAP_TIME_INTERVAL)
mExitViaDoubleTapBack = preferences.getBoolean("exitViaDoubleTapBack", false)
mGesturesEnabled = preferences.getBoolean(GestureProcessor.PREF_KEY, false)
if (mGesturesEnabled) {
mGestureProcessor.init(preferences)
exitViaDoubleTapBack = preferences.getBoolean("exitViaDoubleTapBack", false)
gesturesEnabled = preferences.getBoolean(GestureProcessor.PREF_KEY, false)
if (gesturesEnabled) {
gestureProcessor.init(preferences)
}
if (preferences.getBoolean("timeoutAnswer", false) || preferences.getBoolean(
"keepScreenOn",
@ -1232,7 +1232,7 @@ abstract class AbstractFlashcardViewer :
protected open fun restoreCollectionPreferences(col: Collection) {
// These are preferences we pull out of the collection instead of SharedPreferences
try {
mShowNextReviewTime = col.config.get("estTimes") ?: true
showNextReviewTime = col.config.get("estTimes") ?: true
val preferences = baseContext.sharedPrefs()
automaticAnswer = AutomaticAnswer.createInstance(this, preferences, col)
} catch (ex: Exception) {
@ -1252,8 +1252,8 @@ abstract class AbstractFlashcardViewer :
if (webView == null) {
webView = createWebView()
initializeDebugging(this.sharedPrefs())
mCardFrame!!.addView(webView)
mGestureDetectorImpl.onWebViewCreated(webView!!)
cardFrame!!.addView(webView)
gestureDetectorImpl.onWebViewCreated(webView!!)
}
if (webView!!.visibility != View.VISIBLE) {
webView!!.visibility = View.VISIBLE
@ -1305,7 +1305,7 @@ abstract class AbstractFlashcardViewer :
open fun displayCardQuestion() {
Timber.d("displayCardQuestion()")
displayAnswer = false
mBackButtonPressedToReturn = false
backButtonPressedToReturn = false
setInterface()
typeAnswer?.input = ""
typeAnswer?.updateInfo(currentCard!!, resources)
@ -1316,7 +1316,7 @@ abstract class AbstractFlashcardViewer :
} else {
answerField?.visibility = View.GONE
}
val content = mHtmlGenerator!!.generateHtml(currentCard!!, Side.FRONT)
val content = htmlGenerator!!.generateHtml(currentCard!!, Side.FRONT)
automaticAnswer.onDisplayQuestion()
updateCard(content)
hideEaseButtons()
@ -1333,7 +1333,7 @@ abstract class AbstractFlashcardViewer :
actualHideEaseButtons()
Timber.d("displayCardAnswer()")
mMissingImageHandler.onCardSideChange()
mBackButtonPressedToReturn = false
backButtonPressedToReturn = false
// prevent answering (by e.g. gestures) before card is loaded
if (currentCard == null) {
@ -1356,8 +1356,8 @@ abstract class AbstractFlashcardViewer :
if (!typeAnswer!!.useInputTag) {
typeAnswer!!.input = answerField!!.text.toString()
}
mIsSelecting = false
val answerContent = mHtmlGenerator!!.generateHtml(currentCard!!, Side.BACK)
isSelecting = false
val answerContent = htmlGenerator!!.generateHtml(currentCard!!, Side.BACK)
automaticAnswer.onDisplayAnswer()
updateCard(answerContent)
displayAnswerBottomBar()
@ -1435,7 +1435,7 @@ abstract class AbstractFlashcardViewer :
}
if (!soundPlayer.config.autoplay && !doAudioReplay) return
// Use TTS if TTS preference enabled and no other sound source
val useTTS = mTTS.enabled && !soundPlayer.hasSounds(displayAnswer)
val useTTS = tts.enabled && !soundPlayer.hasSounds(displayAnswer)
// We need to play the sounds from the proper side of the card
if (!useTTS) {
launchCatchingTask {
@ -1450,7 +1450,7 @@ abstract class AbstractFlashcardViewer :
val replayQuestion = soundPlayer.config.replayQuestion
// Text to speech is in effect here
// If the question is displayed or if the question should be replayed, read the question
if (mTtsInitialized) {
if (ttsInitialized) {
if (!displayAnswer || doAudioReplay && replayQuestion) {
readCardTts(SingleSoundSide.QUESTION)
}
@ -1458,14 +1458,14 @@ abstract class AbstractFlashcardViewer :
readCardTts(SingleSoundSide.ANSWER)
}
} else {
mReplayOnTtsInit = true
replayOnTtsInit = true
}
}
@VisibleForTesting
fun readCardTts(side: SingleSoundSide) {
val tags = legacyGetTtsTags(currentCard!!, side, this)
mTTS.readCardText(tags, currentCard!!, side.toSoundSide())
tts.readCardText(tags, currentCard!!, side.toSoundSide())
}
/**
@ -1484,8 +1484,8 @@ abstract class AbstractFlashcardViewer :
* Shows the dialogue for selecting TTS for the current card and cardside.
*/
protected fun showSelectTtsDialogue() {
if (mTtsInitialized) {
mTTS.selectTts(
if (ttsInitialized) {
tts.selectTts(
this,
currentCard!!,
if (displayAnswer) SoundSide.ANSWER else SoundSide.QUESTION
@ -1500,7 +1500,7 @@ abstract class AbstractFlashcardViewer :
return
}
processCardAction { cardWebView: WebView? -> loadContentIntoCard(cardWebView, cardContent!!) }
mGestureDetectorImpl.onFillFlashcard()
gestureDetectorImpl.onFillFlashcard()
if (!displayAnswer) {
updateForNewCard()
}
@ -1520,17 +1520,17 @@ abstract class AbstractFlashcardViewer :
}
protected open fun unblockControls() {
mCardFrame!!.isEnabled = true
cardFrame!!.isEnabled = true
flipCardLayout?.isEnabled = true
easeButton1?.unblockBasedOnEase(mCurrentEase)
easeButton2?.unblockBasedOnEase(mCurrentEase)
easeButton3?.unblockBasedOnEase(mCurrentEase)
easeButton4?.unblockBasedOnEase(mCurrentEase)
easeButton1?.unblockBasedOnEase(currentEase)
easeButton2?.unblockBasedOnEase(currentEase)
easeButton3?.unblockBasedOnEase(currentEase)
easeButton4?.unblockBasedOnEase(currentEase)
if (typeAnswer?.validForEditText() == true) {
answerField?.isEnabled = true
}
mTouchLayer?.visibility = View.VISIBLE
mInAnswer = false
touchLayer?.visibility = View.VISIBLE
inAnswer = false
invalidateOptionsMenu()
}
@ -1751,7 +1751,7 @@ abstract class AbstractFlashcardViewer :
override val baseSnackbarBuilder: SnackbarBuilder = {
// Configure the snackbar to avoid the bottom answer buttons
if (mAnswerButtonsPosition == "bottom") {
if (answerButtonsPosition == "bottom") {
val easeButtons = findViewById<View>(R.id.answer_options_layout)
val previewButtons = findViewById<View>(R.id.preview_buttons_layout)
anchorView = if (previewButtons.isVisible) previewButtons else easeButtons
@ -1804,8 +1804,8 @@ abstract class AbstractFlashcardViewer :
protected open fun closeReviewer(result: Int) {
automaticAnswer.disable()
mPreviousAnswerIndicator!!.stopAutomaticHide()
mLongClickHandler.removeCallbacks(mStartLongClickAction)
previousAnswerIndicator!!.stopAutomaticHide()
longClickHandler.removeCallbacks(startLongClickAction)
this@AbstractFlashcardViewer.setResult(result)
finish()
}
@ -1827,7 +1827,7 @@ abstract class AbstractFlashcardViewer :
if (!isDisplayingAnswer) {
Timber.d("displayCardQuestion()")
displayAnswer = false
mBackButtonPressedToReturn = false
backButtonPressedToReturn = false
setInterface()
typeAnswer?.input = ""
typeAnswer?.updateInfo(currentCard!!, resources)
@ -1838,7 +1838,7 @@ abstract class AbstractFlashcardViewer :
} else {
answerField?.visibility = View.GONE
}
val content = mHtmlGenerator!!.generateHtml(currentCard!!, Side.FRONT)
val content = htmlGenerator!!.generateHtml(currentCard!!, Side.FRONT)
automaticAnswer.onDisplayQuestion()
updateCard(content)
hideEaseButtons()
@ -1870,13 +1870,13 @@ abstract class AbstractFlashcardViewer :
override fun onScrollChanged(horiz: Int, vert: Int, oldHoriz: Int, oldVert: Int) {
super.onScrollChanged(horiz, vert, oldHoriz, oldVert)
if (abs(horiz - oldHoriz) > abs(vert - oldVert)) {
mIsXScrolling = true
mScrollHandler.removeCallbacks(mScrollXRunnable)
mScrollHandler.postDelayed(mScrollXRunnable, 300)
isXScrolling = true
scrollHandler.removeCallbacks(scrollXRunnable)
scrollHandler.postDelayed(scrollXRunnable, 300)
} else {
mIsYScrolling = true
mScrollHandler.removeCallbacks(mScrollYRunnable)
mScrollHandler.postDelayed(mScrollYRunnable, 300)
isYScrolling = true
scrollHandler.removeCallbacks(scrollYRunnable)
scrollHandler.postDelayed(scrollYRunnable, 300)
}
}
@ -1911,9 +1911,9 @@ abstract class AbstractFlashcardViewer :
return null
}
private val mScrollHandler = newHandler()
private val mScrollXRunnable = Runnable { mIsXScrolling = false }
private val mScrollYRunnable = Runnable { mIsYScrolling = false }
private val scrollHandler = newHandler()
private val scrollXRunnable = Runnable { isXScrolling = false }
private val scrollYRunnable = Runnable { isYScrolling = false }
}
internal open inner class MyGestureDetector : SimpleOnGestureListener() {
@ -1935,18 +1935,18 @@ abstract class AbstractFlashcardViewer :
// Go back to immersive mode if the user had temporarily exited it (and then execute swipe gesture)
this@AbstractFlashcardViewer.onFling()
if (e1 != null && mGesturesEnabled) {
if (e1 != null && gesturesEnabled) {
try {
val dy = e2.y - e1.y
val dx = e2.x - e1.x
mGestureProcessor.onFling(
gestureProcessor.onFling(
dx,
dy,
velocityX,
velocityY,
mIsSelecting,
mIsXScrolling,
mIsYScrolling
isSelecting,
isXScrolling,
isYScrolling
)
} catch (e: Exception) {
Timber.e(e, "onFling Exception")
@ -1956,15 +1956,15 @@ abstract class AbstractFlashcardViewer :
}
private fun isTouchingEdge(e1: MotionEvent): Boolean {
val height = mTouchLayer!!.height
val width = mTouchLayer!!.width
val height = touchLayer!!.height
val width = touchLayer!!.width
val margin = Companion.NO_GESTURE_BORDER_DIP * resources.displayMetrics.density + 0.5f
return e1.x < margin || e1.y < margin || height - e1.y < margin || width - e1.x < margin
}
override fun onDoubleTap(e: MotionEvent): Boolean {
if (mGesturesEnabled) {
mGestureProcessor.onDoubleTap()
if (gesturesEnabled) {
gestureProcessor.onDoubleTap()
}
return true
}
@ -1983,14 +1983,14 @@ abstract class AbstractFlashcardViewer :
}
protected open fun executeTouchCommand(e: MotionEvent) {
if (mGesturesEnabled && !mIsSelecting) {
val height = mTouchLayer!!.height
val width = mTouchLayer!!.width
if (gesturesEnabled && !isSelecting) {
val height = touchLayer!!.height
val width = touchLayer!!.width
val posX = e.x
val posY = e.y
mGestureProcessor.onTap(height, width, posX, posY)
gestureProcessor.onTap(height, width, posX, posY)
}
mIsSelecting = false
isSelecting = false
}
open fun onWebViewCreated(webView: WebView) {
@ -2032,7 +2032,7 @@ abstract class AbstractFlashcardViewer :
private fun initShakeDetector() {
Timber.d("Initializing shake detector")
if (mGestureProcessor.isBound(Gesture.SHAKE)) {
if (gestureProcessor.isBound(Gesture.SHAKE)) {
val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
shakeDetector = ShakeDetector(this).apply {
start(sensorManager, SensorManager.SENSOR_DELAY_UI)
@ -2052,25 +2052,25 @@ abstract class AbstractFlashcardViewer :
}
/** A list of events to process when listening to WebView touches */
private val mDesiredTouchEvents = hashSetInit<MotionEvent>(2)
private val desiredTouchEvents = hashSetInit<MotionEvent>(2)
/** A list of events we sent to the WebView (to block double-processing) */
private val mDispatchedTouchEvents = hashSetInit<MotionEvent>(2)
private val dispatchedTouchEvents = hashSetInit<MotionEvent>(2)
override fun hearShake() {
Timber.d("Shake detected!")
mGestureProcessor.onShake()
gestureProcessor.onShake()
}
override fun onFillFlashcard() {
Timber.d("Removing pending touch events for gestures")
mDesiredTouchEvents.clear()
mDispatchedTouchEvents.clear()
desiredTouchEvents.clear()
dispatchedTouchEvents.clear()
}
override fun eventCanBeSentToWebView(event: MotionEvent): Boolean {
// if we processed the event, we don't want to perform it again
return !mDispatchedTouchEvents.remove(event)
return !dispatchedTouchEvents.remove(event)
}
override fun executeTouchCommand(e: MotionEvent) {
@ -2079,12 +2079,12 @@ abstract class AbstractFlashcardViewer :
upEvent.action = MotionEvent.ACTION_UP
// mark the events we want to process
mDesiredTouchEvents.add(e)
mDesiredTouchEvents.add(upEvent)
desiredTouchEvents.add(e)
desiredTouchEvents.add(upEvent)
// mark the events to can guard against double-processing
mDispatchedTouchEvents.add(e)
mDispatchedTouchEvents.add(upEvent)
dispatchedTouchEvents.add(e)
dispatchedTouchEvents.add(upEvent)
Timber.d("Dispatching touch events")
processCardAction { cardWebView: WebView? ->
cardWebView!!.dispatchTouchEvent(e)
@ -2096,7 +2096,7 @@ abstract class AbstractFlashcardViewer :
override fun onWebViewCreated(webView: WebView) {
Timber.d("Initializing WebView touch handler")
webView.setOnTouchListener { webViewAsView: View, motionEvent: MotionEvent ->
if (!mDesiredTouchEvents.remove(motionEvent)) {
if (!desiredTouchEvents.remove(motionEvent)) {
return@setOnTouchListener false
}
@ -2136,8 +2136,8 @@ abstract class AbstractFlashcardViewer :
/** Callback for when TTS has been initialized. */
fun ttsInitialized() {
mTtsInitialized = true
if (mReplayOnTtsInit) {
ttsInitialized = true
if (replayOnTtsInit) {
playSounds(true)
}
}
@ -2147,7 +2147,7 @@ abstract class AbstractFlashcardViewer :
}
val writeLock: Lock
get() = mCardLock.writeLock()
get() = cardLock.writeLock()
open var currentCard: Card? = null
/** Refreshes the WebView after a crash */
@ -2155,13 +2155,13 @@ abstract class AbstractFlashcardViewer :
// Destroy the current WebView (to ensure WebView is GCed).
// Otherwise, we get the following error:
// "crash wasn't handled by all associated webviews, triggering application crash"
mCardFrame!!.removeAllViews()
mCardFrameParent!!.removeView(mCardFrame)
cardFrame!!.removeAllViews()
cardFrameParent!!.removeView(cardFrame)
// destroy after removal from the view - produces logcat warnings otherwise
destroyWebView(webView)
webView = null
// inflate a new instance of mCardFrame
mCardFrame = inflateNewView<FrameLayout>(R.id.flashcard)
cardFrame = inflateNewView<FrameLayout>(R.id.flashcard)
// Even with the above, I occasionally saw the above error. Manually trigger the GC.
// I'll keep this line unless I see another crash, which would point to another underlying issue.
System.gc()
@ -2169,7 +2169,7 @@ abstract class AbstractFlashcardViewer :
fun recreateWebViewFrame() {
// we need to add at index 0 so gestures still go through.
mCardFrameParent!!.addView(mCardFrame, 0)
cardFrameParent!!.addView(cardFrame, 0)
recreateWebView()
}
@ -2459,7 +2459,7 @@ abstract class AbstractFlashcardViewer :
@TargetApi(Build.VERSION_CODES.O)
override fun onRenderProcessGone(view: WebView, detail: RenderProcessGoneDetail): Boolean {
return mOnRenderProcessGoneDelegate.onRenderProcessGone(view, detail)
return onRenderProcessGoneDelegate.onRenderProcessGone(view, detail)
}
}
@ -2514,7 +2514,7 @@ abstract class AbstractFlashcardViewer :
internal fun showTagsDialog() {
val tags = ArrayList(getColUnsafe.tags.all())
val selTags = ArrayList(currentCard!!.note().tags)
val dialog = mTagsDialogFactory!!.newTagsDialog()
val dialog = tagsDialogFactory!!.newTagsDialog()
.withArguments(TagsDialog.DialogType.EDIT_TAGS, selTags, tags)
showDialogFragment(dialog)
}

View File

@ -61,7 +61,7 @@ open class AnkiDroidJsAPI(private val activity: AbstractFlashcardViewer) {
private val context: Context = activity
// Text to speech
private val mTalker = JavaScriptTTS()
private val talker = JavaScriptTTS()
open fun convertToByteArray(apiContract: ApiContract, boolean: Boolean): ByteArray {
return ApiResult(apiContract.isValid, boolean.toString()).toString().toByteArray()
@ -244,22 +244,22 @@ open class AnkiDroidJsAPI(private val activity: AbstractFlashcardViewer) {
"cardDue" -> convertToByteArray(apiContract, currentCard.due)
"deckName" -> convertToByteArray(apiContract, Decks.basename(activity.getColUnsafe.decks.name(currentCard.did)))
"isActiveNetworkMetered" -> convertToByteArray(apiContract, NetworkUtils.isActiveNetworkMetered())
"ttsSetLanguage" -> convertToByteArray(apiContract, mTalker.setLanguage(apiParams))
"ttsSetLanguage" -> convertToByteArray(apiContract, talker.setLanguage(apiParams))
"ttsSpeak" -> {
val jsonObject = JSONObject(apiParams)
val text = jsonObject.getString("text")
val queueMode = jsonObject.getInt("queueMode")
convertToByteArray(apiContract, mTalker.speak(text, queueMode))
convertToByteArray(apiContract, talker.speak(text, queueMode))
}
"ttsIsSpeaking" -> convertToByteArray(apiContract, mTalker.isSpeaking)
"ttsSetPitch" -> convertToByteArray(apiContract, mTalker.setPitch(apiParams.toFloat()))
"ttsSetSpeechRate" -> convertToByteArray(apiContract, mTalker.setSpeechRate(apiParams.toFloat()))
"ttsIsSpeaking" -> convertToByteArray(apiContract, talker.isSpeaking)
"ttsSetPitch" -> convertToByteArray(apiContract, talker.setPitch(apiParams.toFloat()))
"ttsSetSpeechRate" -> convertToByteArray(apiContract, talker.setSpeechRate(apiParams.toFloat()))
"ttsFieldModifierIsAvailable" -> {
// Know if {{tts}} is supported - issue #10443
// Return false for now
convertToByteArray(apiContract, false)
}
"ttsStop" -> convertToByteArray(apiContract, mTalker.stop())
"ttsStop" -> convertToByteArray(apiContract, talker.stop())
"searchCard" -> {
val intent = Intent(context, CardBrowser::class.java).apply {
putExtra("currentCard", currentCard.id)

View File

@ -1156,7 +1156,7 @@ open class CardBrowser :
return super.onOptionsItemSelected(item)
}
override fun exportDialogsFactory(): ExportDialogsFactory = mExportingDelegate.mDialogsFactory
override fun exportDialogsFactory(): ExportDialogsFactory = mExportingDelegate.dialogsFactory
private fun exportSelected() = launchCatchingTask {
val (type, selectedIds) = viewModel.getSelectionExportData() ?: return@launchCatchingTask

View File

@ -24,6 +24,7 @@ import com.ichi2.compat.CompatHelper.Companion.compat
import com.ichi2.compat.CompatHelper.Companion.getSerializableCompat
import com.ichi2.libanki.NoteTypeId
import com.ichi2.libanki.NotetypeJson
import com.ichi2.utils.KotlinCleanup
import org.json.JSONObject
import timber.log.Timber
import java.io.ByteArrayInputStream
@ -32,22 +33,23 @@ import java.io.File
import java.io.IOException
/** A wrapper for a notetype in JSON format with helpers for editing the notetype. */
@KotlinCleanup("_templateChanges -> use templateChanges")
class CardTemplateNotetype(val notetype: NotetypeJson) {
enum class ChangeType {
ADD, DELETE
}
private var mTemplateChanges = ArrayList<Array<Any>>()
private var _templateChanges = ArrayList<Array<Any>>()
var editedModelFileName: String? = null
fun toBundle(): Bundle = bundleOf(
INTENT_MODEL_FILENAME to saveTempModel(AnkiDroidApp.instance.applicationContext, notetype),
"mTemplateChanges" to mTemplateChanges
"mTemplateChanges" to _templateChanges
)
private fun loadTemplateChanges(bundle: Bundle) {
try {
mTemplateChanges = bundle.getSerializableCompat("mTemplateChanges")!!
_templateChanges = bundle.getSerializableCompat("mTemplateChanges")!!
} catch (e: ClassCastException) {
Timber.e(e, "Unexpected cast failure")
}
@ -137,17 +139,17 @@ class CardTemplateNotetype(val notetype: NotetypeJson) {
Timber.d("getDeleteDbOrds()")
// array containing the original / db-relative ordinals for all pending deletes plus the proposed one
val deletedDbOrds = ArrayList<Int>(mTemplateChanges.size)
val deletedDbOrds = ArrayList<Int>(_templateChanges.size)
// For each entry in the changes list - and the proposed delete - scan for deletes to get original ordinal
for (i in 0..mTemplateChanges.size) {
for (i in 0.._templateChanges.size) {
var ordinalAdjustment = 0
// We need an initializer. Though proposed change is checked last, it's a reasonable default initializer.
var currentChange = arrayOf<Any>(ord, ChangeType.DELETE)
if (i < mTemplateChanges.size) {
if (i < _templateChanges.size) {
// Until we exhaust the pending change list we will use them
currentChange = mTemplateChanges[i]
currentChange = _templateChanges[i]
}
// If the current pending change isn't a delete, it is unimportant here
@ -157,7 +159,7 @@ class CardTemplateNotetype(val notetype: NotetypeJson) {
// If it is a delete, scan previous deletes and shift as necessary for original ord
for (j in 0 until i) {
val previousChange = mTemplateChanges[j]
val previousChange = _templateChanges[j]
// Is previous change a delete? Lower ordinal than current change?
if (previousChange[1] === ChangeType.DELETE && previousChange[0] as Int <= currentChange[0] as Int) {
@ -182,8 +184,8 @@ class CardTemplateNotetype(val notetype: NotetypeJson) {
return
}
val adjustedChanges = adjustedTemplateChanges
for (i in mTemplateChanges.indices) {
val change = mTemplateChanges[i]
for (i in _templateChanges.indices) {
val change = _templateChanges[i]
val adjustedChange = adjustedChanges[i]
Timber.d("dumpChanges() Change %s is ord/type %s/%s", i, change[0], change[1])
Timber.d(
@ -197,7 +199,7 @@ class CardTemplateNotetype(val notetype: NotetypeJson) {
val templateChanges: ArrayList<Array<Any>>
get() {
return mTemplateChanges
return _templateChanges
}
/**
@ -247,8 +249,8 @@ class CardTemplateNotetype(val notetype: NotetypeJson) {
var postChange = false
var ordinalAdjustment = 0
var i = 0
while (i < mTemplateChanges.size) {
val change = mTemplateChanges[i]
while (i < _templateChanges.size) {
val change = _templateChanges[i]
var ordinal = change[0] as Int
val changeType = change[1] as ChangeType
Timber.d("compactTemplateChanges() examining change entry %s / %s", ordinal, changeType)
@ -259,7 +261,7 @@ class CardTemplateNotetype(val notetype: NotetypeJson) {
Timber.d("compactTemplateChanges() found our entry at index %s", i)
// Remove this entry to start compaction, then fix up the loop counter since we altered size
postChange = true
mTemplateChanges.removeAt(i)
_templateChanges.removeAt(i)
i--
}
i++

View File

@ -40,19 +40,19 @@ import java.io.IOException
*/
@NeedsTest("after switch to new schema as default, add test to confirm audio tags rendered")
open class CardTemplatePreviewer : AbstractFlashcardViewer() {
private var mEditedModelFileName: String? = null
private var mEditedNotetype: NotetypeJson? = null
private var mOrdinal = 0
private var editedModelFileName: String? = null
private var editedNotetype: NotetypeJson? = null
private var ordinal = 0
/** The index of the card in cardList to show */
private var mCardListIndex = 0
private var cardListIndex = 0
/** The list (currently singular) of cards to be previewed
* A single template was selected, and there was an associated card which exists
*/
private var mCardList: LongArray? = null
private var mNoteEditorBundle: Bundle? = null
private var mShowingAnswer = false
private var cardList: LongArray? = null
private var noteEditorBundle: Bundle? = null
private var showingAnswer = false
/**
* The number of valid cards for the note
@ -68,8 +68,8 @@ open class CardTemplatePreviewer : AbstractFlashcardViewer() {
*/
var cardIndex = 0
private set
private var mAllFieldsNull = true
private var mCardType: String? = null
private var allFieldsNull = true
private var cardType: String? = null
protected var previewLayout: PreviewLayout? = null
override fun onCreate(savedInstanceState: Bundle?) {
if (showedActivityFailedScreen(savedInstanceState)) {
@ -81,20 +81,20 @@ open class CardTemplatePreviewer : AbstractFlashcardViewer() {
parameters = intent.extras
}
if (parameters != null) {
mNoteEditorBundle = parameters.getBundle("noteEditorBundle")
mEditedModelFileName = parameters.getString(CardTemplateNotetype.INTENT_MODEL_FILENAME)
mCardList = parameters.getLongArray("cardList")
mOrdinal = parameters.getInt("ordinal")
mCardListIndex = parameters.getInt("cardListIndex")
mShowingAnswer = parameters.getBoolean("showingAnswer", mShowingAnswer)
noteEditorBundle = parameters.getBundle("noteEditorBundle")
editedModelFileName = parameters.getString(CardTemplateNotetype.INTENT_MODEL_FILENAME)
cardList = parameters.getLongArray("cardList")
ordinal = parameters.getInt("ordinal")
cardListIndex = parameters.getInt("cardListIndex")
showingAnswer = parameters.getBoolean("showingAnswer", showingAnswer)
}
if (mEditedModelFileName != null) {
Timber.d("onCreate() loading edited model from %s", mEditedModelFileName)
if (editedModelFileName != null) {
Timber.d("onCreate() loading edited model from %s", editedModelFileName)
try {
mEditedNotetype = CardTemplateNotetype.getTempModel(mEditedModelFileName!!)
mCardType = mEditedNotetype!!.optString("name")
editedNotetype = CardTemplateNotetype.getTempModel(editedModelFileName!!)
cardType = editedNotetype!!.optString("name")
} catch (e: IOException) {
Timber.w(e, "Unable to load temp model from file %s", mEditedModelFileName)
Timber.w(e, "Unable to load temp model from file %s", editedModelFileName)
closeCardTemplatePreviewer()
}
}
@ -106,7 +106,7 @@ open class CardTemplatePreviewer : AbstractFlashcardViewer() {
override fun onResume() {
super.onResume()
if (currentCard == null || mOrdinal < 0) {
if (currentCard == null || ordinal < 0) {
Timber.e("CardTemplatePreviewer started with empty card list or invalid index")
closeCardTemplatePreviewer()
}
@ -142,7 +142,7 @@ open class CardTemplatePreviewer : AbstractFlashcardViewer() {
topBarLayout!!.visibility = View.GONE
findViewById<View>(R.id.answer_options_layout).visibility = View.GONE
findViewById<View>(R.id.bottom_area_layout).visibility = View.VISIBLE
previewLayout = createAndDisplay(this, mToggleAnswerHandler)
previewLayout = createAndDisplay(this, toggleAnswerHandler)
previewLayout!!.setOnPreviousCard { onPreviousCard() }
previewLayout!!.setOnNextCard { onNextCard() }
previewLayout!!.hideNavigationButtons()
@ -151,16 +151,16 @@ open class CardTemplatePreviewer : AbstractFlashcardViewer() {
override fun displayCardQuestion() {
super.displayCardQuestion()
mShowingAnswer = false
showingAnswer = false
previewLayout!!.setShowingAnswer(false)
}
override fun displayCardAnswer() {
if (mAllFieldsNull && mCardType != null && mCardType == getString(R.string.basic_typing_model_name)) {
if (allFieldsNull && cardType != null && cardType == getString(R.string.basic_typing_model_name)) {
answerField!!.setText(getString(R.string.basic_answer_sample_text_user))
}
super.displayCardAnswer()
mShowingAnswer = true
showingAnswer = true
previewLayout!!.setShowingAnswer(true)
}
@ -172,8 +172,8 @@ open class CardTemplatePreviewer : AbstractFlashcardViewer() {
/* do nothing */
}
private val mToggleAnswerHandler = View.OnClickListener {
if (mShowingAnswer) {
private val toggleAnswerHandler = View.OnClickListener {
if (showingAnswer) {
displayCardQuestion()
} else {
displayCardAnswer()
@ -221,21 +221,21 @@ open class CardTemplatePreviewer : AbstractFlashcardViewer() {
}
public override fun onSaveInstanceState(outState: Bundle) {
outState.putString(CardTemplateNotetype.INTENT_MODEL_FILENAME, mEditedModelFileName)
outState.putLongArray("cardList", mCardList)
outState.putInt("ordinal", mOrdinal)
outState.putInt("cardListIndex", mCardListIndex)
outState.putBundle("noteEditorBundle", mNoteEditorBundle)
outState.putBoolean("showingAnswer", mShowingAnswer)
outState.putString(CardTemplateNotetype.INTENT_MODEL_FILENAME, editedModelFileName)
outState.putLongArray("cardList", cardList)
outState.putInt("ordinal", ordinal)
outState.putInt("cardListIndex", cardListIndex)
outState.putBundle("noteEditorBundle", noteEditorBundle)
outState.putBoolean("showingAnswer", showingAnswer)
super.onSaveInstanceState(outState)
}
override fun onCollectionLoaded(col: Collection) {
super.onCollectionLoaded(col)
if (mNoteEditorBundle != null) {
mAllFieldsNull = false
cardIndex = indexFromOrdinal(col, mNoteEditorBundle!!, mOrdinal)
Timber.d("ord %d => idx %d", mOrdinal, cardIndex)
if (noteEditorBundle != null) {
allFieldsNull = false
cardIndex = indexFromOrdinal(col, noteEditorBundle!!, ordinal)
Timber.d("ord %d => idx %d", ordinal, cardIndex)
// loading from the note editor
val toPreview = setCurrentCardFromNoteEditorBundle(col)
if (toPreview != null) {
@ -246,13 +246,13 @@ open class CardTemplatePreviewer : AbstractFlashcardViewer() {
}
} else {
// loading from the card template editor
mAllFieldsNull = true
allFieldsNull = true
// card template with associated card due to opening from note editor
if (mCardList != null && mCardListIndex >= 0 && mCardListIndex < mCardList!!.size) {
currentCard = PreviewerCard(col, mCardList!![mCardListIndex])
} else if (mEditedNotetype != null) { // bare note type (not coming from note editor), or new card template
if (cardList != null && cardListIndex >= 0 && cardListIndex < cardList!!.size) {
currentCard = PreviewerCard(col, cardList!![cardListIndex])
} else if (editedNotetype != null) { // bare note type (not coming from note editor), or new card template
Timber.d("onCreate() CardTemplatePreviewer started with edited model and template index, displaying blank to preview formatting")
currentCard = getDummyCard(mEditedNotetype!!, mOrdinal)
currentCard = getDummyCard(editedNotetype!!, ordinal)
if (currentCard == null) {
showThemedToast(applicationContext, getString(R.string.invalid_template), false)
closeCardTemplatePreviewer()
@ -265,7 +265,7 @@ open class CardTemplatePreviewer : AbstractFlashcardViewer() {
return
}
displayCardQuestion()
if (mShowingAnswer) {
if (showingAnswer) {
displayCardAnswer()
}
showBackIcon()
@ -276,19 +276,19 @@ open class CardTemplatePreviewer : AbstractFlashcardViewer() {
}
private fun setCurrentCardFromNoteEditorBundle(col: Collection): Card? {
assert(mNoteEditorBundle != null)
currentCard = getDummyCard(mEditedNotetype, cardIndex, getBundleEditFields(mNoteEditorBundle))
assert(noteEditorBundle != null)
currentCard = getDummyCard(editedNotetype, cardIndex, getBundleEditFields(noteEditorBundle))
// example: a basic card with no fields provided
if (currentCard == null) {
return null
}
val newDid = mNoteEditorBundle!!.getLong("did")
val newDid = noteEditorBundle!!.getLong("did")
if (col.decks.isDyn(newDid)) {
currentCard!!.oDid = currentCard!!.did
}
currentCard!!.did = newDid
val currentNote = currentCard!!.note()
val tagsList = mNoteEditorBundle!!.getStringArrayList("tags")
val tagsList = noteEditorBundle!!.getStringArrayList("tags")
setTags(currentNote, tagsList)
return currentCard
}
@ -310,10 +310,10 @@ open class CardTemplatePreviewer : AbstractFlashcardViewer() {
}
private fun getLabels(fieldValues: MutableList<String>) {
if (mCardType != null && mCardType == getString(R.string.cloze_model_name)) {
if (cardType != null && cardType == getString(R.string.cloze_model_name)) {
fieldValues[0] = getString(R.string.cloze_sample_text, "c1")
}
if (mCardType != null && mCardType == getString(R.string.basic_typing_model_name)) {
if (cardType != null && cardType == getString(R.string.basic_typing_model_name)) {
fieldValues[1] = getString(R.string.basic_answer_sample_text)
}
}
@ -332,14 +332,14 @@ open class CardTemplatePreviewer : AbstractFlashcardViewer() {
}
private fun indexFromOrdinal(col: Collection, fieldsBundle: Bundle, ordinal: Int): Int {
return when (mEditedNotetype?.isCloze) {
return when (editedNotetype?.isCloze) {
true -> {
val note = col.newNote(mEditedNotetype!!).apply {
val note = col.newNote(editedNotetype!!).apply {
for ((index, field) in getBundleEditFields(fieldsBundle).withIndex()) {
this.setField(index, field)
}
}
val clozeNumber = mOrdinal + 1
val clozeNumber = this.ordinal + 1
col.clozeNumbersInNote(note).indexOf(clozeNumber)
}
else -> ordinal
@ -363,15 +363,15 @@ open class CardTemplatePreviewer : AbstractFlashcardViewer() {
if (notetype == null) {
return null
}
if (mAllFieldsNull) {
if (allFieldsNull) {
getLabels(fieldValues)
}
val n = getColUnsafe.newNote(notetype)
var i = 0
while (i < fieldValues.size && i < n.fields.size) {
if (mAllFieldsNull) {
if (mCardType != null && mCardType == getString(R.string.cloze_model_name) && i == 0 ||
mCardType == getString(R.string.basic_typing_model_name) && i == 1
if (allFieldsNull) {
if (cardType != null && cardType == getString(R.string.cloze_model_name) && i == 0 ||
cardType == getString(R.string.basic_typing_model_name) && i == 1
) {
n.setField(i, fieldValues[i])
} else {
@ -393,27 +393,27 @@ open class CardTemplatePreviewer : AbstractFlashcardViewer() {
/** Override certain aspects of Card behavior so we may display unsaved data */
inner class PreviewerCard(col: Collection, id: Long) : Card(col, id) {
private val mNote: Note? = null
private val _note: Note? = null
/* if we have an unsaved note saved, use it instead of a collection lookup */
override fun note(
reload: Boolean
): Note {
return mNote ?: super.note(reload)
return _note ?: super.note(reload)
}
/** if we have an unsaved note saved, use it instead of a collection lookup */
override fun note(): Note {
return mNote ?: super.note()
return _note ?: super.note()
}
/** if we have an unsaved note, never return empty */
val isEmpty: Boolean
get() = mNote != null
get() = _note != null
/** Override the method that fetches the model so we can render unsaved models */
override fun model(): NotetypeJson {
return mEditedNotetype ?: super.model()
return editedNotetype ?: super.model()
}
override fun renderOutput(reload: Boolean, browser: Boolean): TemplateRenderOutput {

View File

@ -151,19 +151,19 @@ const val OLDEST_WORKING_WEBVIEW_VERSION = 77
* Responsibilities:
* * Setup/upgrades of the application: [handleStartup]
* * Error handling [handleDbError] [handleDbLocked]
* * Displaying a tree of decks, some of which may be collapsible: [mDeckListAdapter]
* * Displaying a tree of decks, some of which may be collapsible: [deckListAdapter]
* * Allows users to study the decks
* * Displays deck progress
* * A long press opens a menu allowing modification of the deck
* * Filtering decks (if more than 10) [mToolbarSearchView]
* * Filtering decks (if more than 10) [toolbarSearchView]
* * Controlling syncs
* * A user may [pull down][mPullToSyncWrapper] on the 'tree view' to sync
* * A user may [pull down][pullToSyncWrapper] on the 'tree view' to sync
* * A [button][updateSyncIconFromState] which relies on [SyncStatus] to display whether a sync is needed
* * Blocks the UI and displays sync progress when syncing
* * Displaying 'General' AnkiDroid options: backups, import, 'check media' etc...
* * General handler for error/global dialogs (search for 'as DeckPicker')
* * Such as import: [ImportDialogListener]
* * A Floating Action Button [mFloatingActionMenu] allowing the user to quickly add notes/cards.
* * A Floating Action Button [floatingActionMenu] allowing the user to quickly add notes/cards.
* * A custom image as a background can be added: [applyDeckPickerBackground]
*/
@KotlinCleanup("lots to do")
@ -187,42 +187,42 @@ open class DeckPicker :
CollectionPermissionScreenLauncher,
ExportDialogsFactoryProvider {
// Short animation duration from system
private var mShortAnimDuration = 0
private var mBackButtonPressedToExit = false
private lateinit var mDeckPickerContent: RelativeLayout
private var shortAnimDuration = 0
private var backButtonPressedToExit = false
private lateinit var deckPickerContent: RelativeLayout
@Suppress("Deprecation") // TODO: Encapsulate ProgressDialog within a class to limit the use of deprecated functionality
var mProgressDialog: android.app.ProgressDialog? = null
private var mStudyoptionsFrame: View? = null // not lateInit - can be null
var progressDialog: android.app.ProgressDialog? = null
private var studyoptionsFrame: View? = null // not lateInit - can be null
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
lateinit var recyclerView: RecyclerView
private lateinit var mRecyclerViewLayoutManager: LinearLayoutManager
private lateinit var mDeckListAdapter: DeckAdapter
private val mSnackbarShowHideCallback = Snackbar.Callback()
lateinit var mExportingDelegate: ActivityExportingDelegate
private lateinit var mNoDecksPlaceholder: LinearLayout
lateinit var mPullToSyncWrapper: SwipeRefreshLayout
private lateinit var recyclerViewLayoutManager: LinearLayoutManager
private lateinit var deckListAdapter: DeckAdapter
private val snackbarShowHideCallback = Snackbar.Callback()
lateinit var exportingDelegate: ActivityExportingDelegate
private lateinit var noDecksPlaceholder: LinearLayout
lateinit var pullToSyncWrapper: SwipeRefreshLayout
private set
private lateinit var mReviewSummaryTextView: TextView
private lateinit var reviewSummaryTextView: TextView
@KotlinCleanup("make lateinit, but needs more changes")
private var mUnmountReceiver: BroadcastReceiver? = null
private lateinit var mFloatingActionMenu: DeckPickerFloatingActionMenu
private var unmountReceiver: BroadcastReceiver? = null
private lateinit var floatingActionMenu: DeckPickerFloatingActionMenu
// flag asking user to do a full sync which is used in upgrade path
private var mRecommendFullSync = false
private var recommendFullSync = false
override val baseSnackbarBuilder: SnackbarBuilder = {
anchorView = findViewById<FloatingActionButton>(R.id.fab_main)
}
// flag keeping track of when the app has been paused
var mActivityPaused = false
var activityPaused = false
private set
// Flag to keep track of startup error
private var mStartupError = false
private var startupError = false
/** See [OptionsMenuState]. */
@VisibleForTesting
@ -239,7 +239,7 @@ open class DeckPicker :
* Since syncing closes the database, this flag allows us to avoid doing any
* work in onResume that might use the database and go straight to syncing.
*/
private var mSyncOnResume = false
private var syncOnResume = false
/**
* Keep track of which deck was last given focus in the deck list. If we find that this value
@ -247,12 +247,12 @@ open class DeckPicker :
* deck.
*/
@VisibleForTesting
internal var mFocusedDeck: DeckId = 0
internal var focusedDeck: DeckId = 0
var importColpkgListener: ImportColpkgListener? = null
private var mToolbarSearchView: SearchView? = null
private lateinit var mCustomStudyDialogFactory: CustomStudyDialogFactory
private var toolbarSearchView: SearchView? = null
private lateinit var customStudyDialogFactory: CustomStudyDialogFactory
override val permissionScreenLauncher = recreateActivityResultLauncher()
@ -274,7 +274,7 @@ open class DeckPicker :
ActivityResultContracts.StartActivityForResult(),
DeckPickerActivityResultCallback {
if (it.resultCode == RESULT_OK) {
mSyncOnResume = true
syncOnResume = true
}
}
)
@ -332,11 +332,11 @@ open class DeckPicker :
// ----------------------------------------------------------------------------
// LISTENERS
// ----------------------------------------------------------------------------
private val mDeckExpanderClickListener = View.OnClickListener { view: View ->
private val deckExpanderClickListener = View.OnClickListener { view: View ->
launchCatchingTask { toggleDeckExpand(view.tag as Long) }
}
private val mDeckClickListener = View.OnClickListener { v: View -> onDeckClick(v, DeckSelectionType.DEFAULT) }
private val mCountsClickListener = View.OnClickListener { v: View -> onDeckClick(v, DeckSelectionType.SHOW_STUDY_OPTIONS) }
private val deckClickListener = View.OnClickListener { v: View -> onDeckClick(v, DeckSelectionType.DEFAULT) }
private val countsClickListener = View.OnClickListener { v: View -> onDeckClick(v, DeckSelectionType.SHOW_STUDY_OPTIONS) }
private fun onDeckClick(v: View, selectionType: DeckSelectionType) {
val deckId = v.tag as Long
Timber.i("DeckPicker:: Selected deck with id %d", deckId)
@ -345,13 +345,13 @@ open class DeckPicker :
if (fragmented) {
// Calling notifyDataSetChanged() will update the color of the selected deck.
// This interferes with the ripple effect, so we don't do it if lollipop and not tablet view
mDeckListAdapter.notifyDataSetChanged()
deckListAdapter.notifyDataSetChanged()
updateDeckList()
}
}
}
private val mDeckLongClickListener = OnLongClickListener { v ->
private val deckLongClickListener = OnLongClickListener { v ->
val deckId = v.tag as DeckId
Timber.i("DeckPicker:: Long tapped on deck with id %d", deckId)
launchCatchingTask {
@ -385,8 +385,8 @@ open class DeckPicker :
if (showedActivityFailedScreen(savedInstanceState)) {
return
}
mExportingDelegate = ActivityExportingDelegate(this) { getColUnsafe }
mCustomStudyDialogFactory = CustomStudyDialogFactory({ getColUnsafe }, this).attachToActivity(this)
exportingDelegate = ActivityExportingDelegate(this) { getColUnsafe }
customStudyDialogFactory = CustomStudyDialogFactory({ getColUnsafe }, this).attachToActivity(this)
// Then set theme and content view
super.onCreate(savedInstanceState)
@ -404,7 +404,7 @@ open class DeckPicker :
}
if (intent.hasExtra(INTENT_SYNC_FROM_LOGIN)) {
Timber.d("launched from introduction activity login: syncing")
mSyncOnResume = true
syncOnResume = true
}
setContentView(R.layout.homescreen)
@ -412,12 +412,12 @@ open class DeckPicker :
val mainView = findViewById<View>(android.R.id.content)
// check, if tablet layout
mStudyoptionsFrame = findViewById(R.id.studyoptions_fragment)
studyoptionsFrame = findViewById(R.id.studyoptions_fragment)
// set protected variable from NavigationDrawerActivity
fragmented = mStudyoptionsFrame != null && mStudyoptionsFrame!!.visibility == View.VISIBLE
fragmented = studyoptionsFrame != null && studyoptionsFrame!!.visibility == View.VISIBLE
// Open StudyOptionsFragment if in fragmented mode
if (fragmented && !mStartupError) {
if (fragmented && !startupError) {
loadStudyOptionsFragment(false)
}
registerExternalStorageListener()
@ -426,20 +426,20 @@ open class DeckPicker :
initNavigationDrawer(mainView)
title = resources.getString(R.string.app_name)
mDeckPickerContent = findViewById(R.id.deck_picker_content)
deckPickerContent = findViewById(R.id.deck_picker_content)
recyclerView = findViewById(R.id.files)
mNoDecksPlaceholder = findViewById(R.id.no_decks_placeholder)
noDecksPlaceholder = findViewById(R.id.no_decks_placeholder)
mDeckPickerContent.visibility = View.GONE
mNoDecksPlaceholder.visibility = View.GONE
deckPickerContent.visibility = View.GONE
noDecksPlaceholder.visibility = View.GONE
// specify a LinearLayoutManager and set up item dividers for the RecyclerView
mRecyclerViewLayoutManager = LinearLayoutManager(this)
recyclerView.layoutManager = mRecyclerViewLayoutManager
recyclerViewLayoutManager = LinearLayoutManager(this)
recyclerView.layoutManager = recyclerViewLayoutManager
val ta = this.obtainStyledAttributes(intArrayOf(R.attr.deckDivider))
val divider = ta.getDrawable(0)
ta.recycle()
val dividerDecorator = DividerItemDecoration(this, mRecyclerViewLayoutManager.orientation)
val dividerDecorator = DividerItemDecoration(this, recyclerViewLayoutManager.orientation)
dividerDecorator.setDrawable(divider!!)
recyclerView.addItemDecoration(dividerDecorator)
@ -456,37 +456,37 @@ open class DeckPicker :
Timber.w(e, "Failed to apply background")
showThemedToast(this, getString(R.string.failed_to_apply_background_image, e.localizedMessage), false)
}
mExportingDelegate.onRestoreInstanceState(savedInstanceState)
exportingDelegate.onRestoreInstanceState(savedInstanceState)
// create and set an adapter for the RecyclerView
mDeckListAdapter = DeckAdapter(layoutInflater, this).apply {
setDeckClickListener(mDeckClickListener)
setCountsClickListener(mCountsClickListener)
setDeckExpanderClickListener(mDeckExpanderClickListener)
setDeckLongClickListener(mDeckLongClickListener)
deckListAdapter = DeckAdapter(layoutInflater, this).apply {
setDeckClickListener(deckClickListener)
setCountsClickListener(countsClickListener)
setDeckExpanderClickListener(deckExpanderClickListener)
setDeckLongClickListener(deckLongClickListener)
enablePartialTransparencyForBackground(hasDeckPickerBackground)
}
recyclerView.adapter = mDeckListAdapter
recyclerView.adapter = deckListAdapter
mPullToSyncWrapper = findViewById<SwipeRefreshLayout?>(R.id.pull_to_sync_wrapper).apply {
pullToSyncWrapper = findViewById<SwipeRefreshLayout?>(R.id.pull_to_sync_wrapper).apply {
setDistanceToTriggerSync(SWIPE_TO_SYNC_TRIGGER_DISTANCE)
setOnRefreshListener {
Timber.i("Pull to Sync: Syncing")
mPullToSyncWrapper.isRefreshing = false
pullToSyncWrapper.isRefreshing = false
sync()
}
viewTreeObserver.addOnScrollChangedListener {
mPullToSyncWrapper.isEnabled = mRecyclerViewLayoutManager.findFirstCompletelyVisibleItemPosition() == 0
pullToSyncWrapper.isEnabled = recyclerViewLayoutManager.findFirstCompletelyVisibleItemPosition() == 0
}
}
// Setup the FloatingActionButtons, should work everywhere with min API >= 15
mFloatingActionMenu = DeckPickerFloatingActionMenu(this, view, this)
floatingActionMenu = DeckPickerFloatingActionMenu(this, view, this)
mReviewSummaryTextView = findViewById(R.id.today_stats_text_view)
reviewSummaryTextView = findViewById(R.id.today_stats_text_view)
mShortAnimDuration = resources.getInteger(android.R.integer.config_shortAnimTime)
shortAnimDuration = resources.getInteger(android.R.integer.config_shortAnimTime)
Onboarding.DeckPicker(this, mRecyclerViewLayoutManager).onCreate()
Onboarding.DeckPicker(this, recyclerViewLayoutManager).onCreate()
launchShowingHidingEssentialFileMigrationProgressDialog()
if (BuildConfig.DEBUG) {
@ -668,7 +668,7 @@ open class DeckPicker :
Timber.d("handleStartup: Continuing. unaffected by storage migration")
val failure = InitialActivity.getStartupFailureType(this)
mStartupError = if (failure == null) {
startupError = if (failure == null) {
// Show any necessary dialogs (e.g. changelog, special messages, etc)
val sharedPrefs = this.sharedPrefs()
showStartupScreensAndDialogs(sharedPrefs, 0)
@ -759,11 +759,11 @@ open class DeckPicker :
override fun onCreateOptionsMenu(menu: Menu): Boolean {
Timber.d("onCreateOptionsMenu()")
mFloatingActionMenu.closeFloatingActionMenu(applyRiseAndShrinkAnimation = false)
floatingActionMenu.closeFloatingActionMenu(applyRiseAndShrinkAnimation = false)
menuInflater.inflate(R.menu.deck_picker, menu)
menu.findItem(R.id.action_export)?.title = TR.exportingExport()
setupSearchIcon(menu.findItem(R.id.deck_picker_action_filter))
mToolbarSearchView = menu.findItem(R.id.deck_picker_action_filter).actionView as SearchView
toolbarSearchView = menu.findItem(R.id.deck_picker_action_filter).actionView as SearchView
// redraw menu synchronously to avoid flicker
updateMenuFromState(menu)
// ...then launch a task to possibly update the visible icons.
@ -870,7 +870,7 @@ open class DeckPicker :
override fun onMenuItemActionExpand(item: MenuItem): Boolean {
Timber.i("DeckPicker:: SearchItem opened")
// Hide the floating action button if it is visible
mFloatingActionMenu.hideFloatingActionButton()
floatingActionMenu.hideFloatingActionButton()
return true
}
@ -878,7 +878,7 @@ open class DeckPicker :
override fun onMenuItemActionCollapse(item: MenuItem): Boolean {
Timber.i("DeckPicker:: SearchItem closed")
// Show the floating action button if it is hidden
mFloatingActionMenu.showFloatingActionButton()
floatingActionMenu.showFloatingActionButton()
return true
}
})
@ -1082,7 +1082,7 @@ open class DeckPicker :
}
}
override fun exportDialogsFactory(): ExportDialogsFactory = mExportingDelegate.mDialogsFactory
override fun exportDialogsFactory(): ExportDialogsFactory = exportingDelegate.dialogsFactory
fun exportCollection() {
if (mediaMigrationIsInProgress(this)) {
@ -1102,7 +1102,7 @@ open class DeckPicker :
}
override fun onResume() {
mActivityPaused = false
activityPaused = false
// stop onResume() processing the message.
// we need to process the message after `loadDeckCounts` is added in refreshState
// As `loadDeckCounts` is cancelled in `migrate()`
@ -1116,10 +1116,10 @@ open class DeckPicker :
fun refreshState() {
// Due to the App Introduction, this may be called before permission has been granted.
if (mSyncOnResume && hasCollectionStoragePermissions()) {
if (syncOnResume && hasCollectionStoragePermissions()) {
Timber.i("Performing Sync on Resume")
sync()
mSyncOnResume = false
syncOnResume = false
} else {
selectNavigationItem(R.id.nav_decks)
updateDeckList()
@ -1131,20 +1131,20 @@ open class DeckPicker :
public override fun onSaveInstanceState(savedInstanceState: Bundle) {
super.onSaveInstanceState(savedInstanceState)
savedInstanceState.putBoolean("mIsFABOpen", mFloatingActionMenu.isFABOpen)
savedInstanceState.putBoolean("mIsFABOpen", floatingActionMenu.isFABOpen)
savedInstanceState.putBoolean("migrateStorageAfterMediaSyncCompleted", migrateStorageAfterMediaSyncCompleted)
importColpkgListener?.let {
if (it is DatabaseRestorationListener) {
savedInstanceState.getString("dbRestorationPath", it.newAnkiDroidDirectory)
}
}
mExportingDelegate.onSaveInstanceState(savedInstanceState)
exportingDelegate.onSaveInstanceState(savedInstanceState)
savedInstanceState.putSerializable("mediaUsnOnConflict", mediaUsnOnConflict)
}
public override fun onRestoreInstanceState(savedInstanceState: Bundle) {
super.onRestoreInstanceState(savedInstanceState)
mFloatingActionMenu.isFABOpen = savedInstanceState.getBoolean("mIsFABOpen")
floatingActionMenu.isFABOpen = savedInstanceState.getBoolean("mIsFABOpen")
migrateStorageAfterMediaSyncCompleted = savedInstanceState.getBoolean("migrateStorageAfterMediaSyncCompleted")
savedInstanceState.getString("dbRestorationPath")?.let { path ->
CollectionHelper.ankiDroidDirectoryOverride = path
@ -1154,7 +1154,7 @@ open class DeckPicker :
}
override fun onPause() {
mActivityPaused = true
activityPaused = true
// The deck count will be computed on resume. No need to compute it now
loadDeckCounts?.cancel()
super.onPause()
@ -1167,11 +1167,11 @@ open class DeckPicker :
override fun onDestroy() {
super.onDestroy()
if (mUnmountReceiver != null) {
unregisterReceiver(mUnmountReceiver)
if (unmountReceiver != null) {
unregisterReceiver(unmountReceiver)
}
if (mProgressDialog != null && mProgressDialog!!.isShowing) {
mProgressDialog!!.dismiss()
if (progressDialog != null && progressDialog!!.isShowing) {
progressDialog!!.dismiss()
}
}
@ -1204,29 +1204,29 @@ open class DeckPicker :
super.onBackPressed()
} else {
Timber.i("Back key pressed")
if (mFloatingActionMenu.isFABOpen) {
mFloatingActionMenu.closeFloatingActionMenu(applyRiseAndShrinkAnimation = true)
if (floatingActionMenu.isFABOpen) {
floatingActionMenu.closeFloatingActionMenu(applyRiseAndShrinkAnimation = true)
} else {
if (!preferences.getBoolean(
"exitViaDoubleTapBack",
false
) || mBackButtonPressedToExit
) || backButtonPressedToExit
) {
automaticSync()
finish()
} else {
showSnackbar(R.string.back_pressed_once, Snackbar.LENGTH_SHORT)
}
mBackButtonPressedToExit = true
backButtonPressedToExit = true
HandlerUtils.executeFunctionWithDelay(Consts.SHORT_TOAST_DURATION) {
mBackButtonPressedToExit = false
backButtonPressedToExit = false
}
}
}
}
override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean {
if (mToolbarSearchView != null && mToolbarSearchView!!.hasFocus()) {
if (toolbarSearchView != null && toolbarSearchView!!.hasFocus()) {
Timber.d("Skipping keypress: search action bar is focused")
return true
}
@ -1274,8 +1274,8 @@ open class DeckPicker :
}
// Force a full sync if flag was set in upgrade path, asking the user to confirm if necessary
if (mRecommendFullSync) {
mRecommendFullSync = false
if (recommendFullSync) {
recommendFullSync = false
try {
getColUnsafe.modSchema()
} catch (e: ConfirmModSchemaException) {
@ -1372,7 +1372,7 @@ open class DeckPicker :
// Recommend the user to do a full-sync if they're upgrading from before 2.3.1beta8
if (previous < 20301208) {
Timber.i("Recommend the user to do a full-sync")
mRecommendFullSync = true
recommendFullSync = true
}
// Fix "font-family" definition in templates created by AnkiDroid before 2.6alpha23
@ -1676,7 +1676,7 @@ open class DeckPicker :
val hkey = preferences.getString("hkey", "")
if (hkey!!.isEmpty()) {
Timber.w("User not logged in")
mPullToSyncWrapper.isRefreshing = false
pullToSyncWrapper.isRefreshing = false
showSyncErrorDialog(SyncErrorDialog.DIALOG_USER_NOT_LOGGED_IN_SYNC)
return
}
@ -1753,8 +1753,8 @@ open class DeckPicker :
* Show a message when the SD card is ejected
*/
private fun registerExternalStorageListener() {
if (mUnmountReceiver == null) {
mUnmountReceiver = object : BroadcastReceiver() {
if (unmountReceiver == null) {
unmountReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (intent.action == SdCardReceiver.MEDIA_EJECT) {
onSdCardNotMounted()
@ -1766,7 +1766,7 @@ open class DeckPicker :
val iFilter = IntentFilter()
iFilter.addAction(SdCardReceiver.MEDIA_EJECT)
iFilter.addAction(SdCardReceiver.MEDIA_MOUNT)
registerReceiver(mUnmountReceiver, iFilter)
registerReceiver(unmountReceiver, iFilter)
}
}
@ -1840,7 +1840,7 @@ open class DeckPicker :
@NeedsTest("14608: Ensure that the deck options refer to the selected deck")
private suspend fun handleDeckSelection(did: DeckId, selectionType: DeckSelectionType) {
fun showEmptyDeckSnackbar() = showSnackbar(R.string.empty_deck) {
addCallback(mSnackbarShowHideCallback)
addCallback(snackbarShowHideCallback)
setAction(R.string.menu_add) { addNote() }
}
@ -1865,8 +1865,8 @@ open class DeckPicker :
withCol { decks.select(did) }
// Also forget the last deck used by the Browser
CardBrowser.clearLastDeckId()
mFocusedDeck = did
val deck = mDeckListAdapter.getNodeByDid(did)
focusedDeck = did
val deck = deckListAdapter.getNodeByDid(did)
if (deck.hasCardsReadyToStudy()) {
openReviewerOrStudyOptions(selectionType)
return
@ -1893,8 +1893,8 @@ open class DeckPicker :
* @param did The deck ID of the deck to select.
*/
private fun scrollDecklistToDeck(did: DeckId) {
val position = mDeckListAdapter.findDeckPosition(did)
mRecyclerViewLayoutManager.scrollToPositionWithOffset(position, recyclerView.height / 2)
val position = deckListAdapter.findDeckPosition(did)
recyclerViewLayoutManager.scrollToPositionWithOffset(position, recyclerView.height / 2)
}
/**
@ -1933,14 +1933,14 @@ open class DeckPicker :
hideProgressBar()
// Make sure the fragment is visible
if (fragmented) {
mStudyoptionsFrame!!.visibility = View.VISIBLE
studyoptionsFrame!!.visibility = View.VISIBLE
}
dueTree = result
launchCatchingTask { renderPage(collectionIsEmpty) }
// Update the mini statistics bar as well
mReviewSummaryTextView.setSingleLine()
reviewSummaryTextView.setSingleLine()
launchCatchingTask {
mReviewSummaryTextView.text = withCol {
reviewSummaryTextView.text = withCol {
sched.studiedToday()
}
}
@ -1960,50 +1960,50 @@ open class DeckPicker :
// Check if default deck is the only available and there are no cards
val isEmpty = tree.children.size == 1 && tree.children[0].did == 1L && collectionIsEmpty
if (animationDisabled()) {
mDeckPickerContent.visibility = if (isEmpty) View.GONE else View.VISIBLE
mNoDecksPlaceholder.visibility = if (isEmpty) View.VISIBLE else View.GONE
deckPickerContent.visibility = if (isEmpty) View.GONE else View.VISIBLE
noDecksPlaceholder.visibility = if (isEmpty) View.VISIBLE else View.GONE
} else {
val translation = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
8f,
resources.displayMetrics
)
val decksListShown = mDeckPickerContent.visibility == View.VISIBLE
val placeholderShown = mNoDecksPlaceholder.visibility == View.VISIBLE
val decksListShown = deckPickerContent.visibility == View.VISIBLE
val placeholderShown = noDecksPlaceholder.visibility == View.VISIBLE
if (isEmpty) {
if (decksListShown) {
fadeOut(mDeckPickerContent, mShortAnimDuration, translation)
fadeOut(deckPickerContent, shortAnimDuration, translation)
}
if (!placeholderShown) {
fadeIn(mNoDecksPlaceholder, mShortAnimDuration, translation).startDelay = if (decksListShown) mShortAnimDuration * 2.toLong() else 0.toLong()
fadeIn(noDecksPlaceholder, shortAnimDuration, translation).startDelay = if (decksListShown) shortAnimDuration * 2.toLong() else 0.toLong()
}
} else {
if (!decksListShown) {
fadeIn(mDeckPickerContent, mShortAnimDuration, translation).startDelay = if (placeholderShown) mShortAnimDuration * 2.toLong() else 0.toLong()
fadeIn(deckPickerContent, shortAnimDuration, translation).startDelay = if (placeholderShown) shortAnimDuration * 2.toLong() else 0.toLong()
}
if (placeholderShown) {
fadeOut(mNoDecksPlaceholder, mShortAnimDuration, translation)
fadeOut(noDecksPlaceholder, shortAnimDuration, translation)
}
}
}
val currentFilter = if (mToolbarSearchView != null) mToolbarSearchView!!.query else null
val currentFilter = if (toolbarSearchView != null) toolbarSearchView!!.query else null
if (isEmpty) {
if (supportActionBar != null) {
supportActionBar!!.subtitle = null
}
if (mToolbarSearchView != null) {
mDeckListAdapter.filter?.filter(currentFilter)
if (toolbarSearchView != null) {
deckListAdapter.filter?.filter(currentFilter)
}
Timber.d("Not rendering deck list as there are no cards")
// We're done here
return
}
mDeckListAdapter.buildDeckList(tree, currentFilter)
deckListAdapter.buildDeckList(tree, currentFilter)
// Set the "x due" subtitle
try {
val due = mDeckListAdapter.due
val due = deckListAdapter.due
val res = resources
if (due != null && supportActionBar != null) {
@ -2019,9 +2019,9 @@ open class DeckPicker :
Timber.e(e, "RuntimeException setting time remaining")
}
val current = withCol { decks.current().optLong("id") }
if (mFocusedDeck != current) {
if (focusedDeck != current) {
scrollDecklistToDeck(current)
mFocusedDeck = current
focusedDeck = current
}
}
@ -2086,7 +2086,7 @@ open class DeckPicker :
createDeckDialog.deckName = currentName
createDeckDialog.setOnNewDeckCreated {
dismissAllDialogFragments()
mDeckListAdapter.notifyDataSetChanged()
deckListAdapter.notifyDataSetChanged()
updateDeckList()
if (fragmented) {
loadStudyOptionsFragment(false)
@ -2209,7 +2209,7 @@ open class DeckPicker :
createDeckDialog.setOnNewDeckCreated {
// a deck was created
dismissAllDialogFragments()
mDeckListAdapter.notifyDataSetChanged()
deckListAdapter.notifyDataSetChanged()
updateDeckList()
if (fragmented) {
loadStudyOptionsFragment(false)
@ -2224,13 +2224,13 @@ open class DeckPicker :
*/
@get:VisibleForTesting(otherwise = VisibleForTesting.NONE)
val visibleDeckCount: Int
get() = mDeckListAdapter.itemCount
get() = deckListAdapter.itemCount
/**
* Check if at least one deck is being displayed.
*/
fun hasAtLeastOneDeckBeingDisplayed(): Boolean {
return mDeckListAdapter.itemCount > 0 && mRecyclerViewLayoutManager.getChildAt(0) != null
return deckListAdapter.itemCount > 0 && recyclerViewLayoutManager.getChildAt(0) != null
}
private enum class DeckSelectionType {
@ -2314,7 +2314,7 @@ open class DeckPicker :
return
}
if (mActivityPaused) {
if (activityPaused) {
sendNotificationForAsyncOperation(MigrateStorageOnSyncSuccess(this.resources), Channel.SYNC)
return
}
@ -2527,7 +2527,7 @@ open class DeckPicker :
sched.hasCardsTodayAfterStudyAheadLimit() -> CompletedDeckStatus.LEARN_AHEAD_LIMIT_REACHED
sched.newDue() || sched.revDue() -> CompletedDeckStatus.LEARN_AHEAD_LIMIT_REACHED
decks.isDyn(did) -> CompletedDeckStatus.DYNAMIC_DECK_NO_LIMITS_REACHED
mDeckListAdapter.getNodeByDid(did).children.isEmpty() && isEmptyDeck(did) -> CompletedDeckStatus.EMPTY_REGULAR_DECK
deckListAdapter.getNodeByDid(did).children.isEmpty() && isEmptyDeck(did) -> CompletedDeckStatus.EMPTY_REGULAR_DECK
else -> CompletedDeckStatus.REGULAR_DECK_NO_MORE_CARDS_TODAY
}
}

View File

@ -43,15 +43,18 @@ import com.ichi2.ui.AnimationUtil.expandView
import com.ichi2.utils.KotlinCleanup
import java.util.*
@KotlinCleanup("replace _name with `field`")
@KotlinCleanup("remove setTypeface")
@KotlinCleanup("replace setEnableAnimation with var")
class FieldEditLine : FrameLayout {
val editText: FieldEditText
private val mLabel: TextView
private val label: TextView
val toggleSticky: ImageButton
val mediaButton: ImageButton
private val mExpandButton: ImageButton
private var mName: String? = null
private var mExpansionState = ExpansionState.EXPANDED
private var mEnableAnimation = true
private val expandButton: ImageButton
private var _name: String? = null
private var expansionState = ExpansionState.EXPANDED
private var enableAnimation = true
constructor(context: Context) : super(context)
@ -62,41 +65,41 @@ class FieldEditLine : FrameLayout {
init {
LayoutInflater.from(context).inflate(R.layout.card_multimedia_editline, this, true)
editText = findViewById(R.id.id_note_editText)
mLabel = findViewById(R.id.id_label)
label = findViewById(R.id.id_label)
toggleSticky = findViewById(R.id.id_toggle_sticky_button)
mediaButton = findViewById(R.id.id_media_button)
val constraintLayout: ConstraintLayout = findViewById(R.id.constraint_layout)
mExpandButton = findViewById(R.id.id_expand_button)
expandButton = findViewById(R.id.id_expand_button)
// 7433 -
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
editText.id = ViewCompat.generateViewId()
toggleSticky.id = ViewCompat.generateViewId()
mediaButton.id = ViewCompat.generateViewId()
mExpandButton.id = ViewCompat.generateViewId()
expandButton.id = ViewCompat.generateViewId()
editText.nextFocusForwardId = toggleSticky.id
toggleSticky.nextFocusForwardId = mediaButton.id
mediaButton.nextFocusForwardId = mExpandButton.id
mediaButton.nextFocusForwardId = expandButton.id
ConstraintSet().apply {
clone(constraintLayout)
connect(toggleSticky.id, ConstraintSet.END, mediaButton.id, ConstraintSet.START)
connect(mediaButton.id, ConstraintSet.END, mExpandButton.id, ConstraintSet.START)
connect(mediaButton.id, ConstraintSet.END, expandButton.id, ConstraintSet.START)
applyTo(constraintLayout)
}
}
setExpanderBackgroundImage()
mExpandButton.setOnClickListener { toggleExpansionState() }
expandButton.setOnClickListener { toggleExpansionState() }
editText.init()
mLabel.setPadding(getDensityAdjustedValue(context, 3.4f).toInt(), 0, 0, 0)
label.setPadding(getDensityAdjustedValue(context, 3.4f).toInt(), 0, 0, 0)
}
private fun toggleExpansionState() {
mExpansionState = when (mExpansionState) {
expansionState = when (expansionState) {
ExpansionState.EXPANDED -> {
collapseView(editText, mEnableAnimation)
collapseView(editText, enableAnimation)
ExpansionState.COLLAPSED
}
ExpansionState.COLLAPSED -> {
expandView(editText, mEnableAnimation)
expandView(editText, enableAnimation)
ExpansionState.EXPANDED
}
}
@ -104,9 +107,9 @@ class FieldEditLine : FrameLayout {
}
private fun setExpanderBackgroundImage() {
when (mExpansionState) {
ExpansionState.COLLAPSED -> mExpandButton.background = getBackgroundImage(R.drawable.ic_expand_more_black_24dp_xml)
ExpansionState.EXPANDED -> mExpandButton.background = getBackgroundImage(R.drawable.ic_expand_less_black_24dp)
when (expansionState) {
ExpansionState.COLLAPSED -> expandButton.background = getBackgroundImage(R.drawable.ic_expand_more_black_24dp_xml)
ExpansionState.EXPANDED -> expandButton.background = getBackgroundImage(R.drawable.ic_expand_less_black_24dp)
}
}
@ -140,19 +143,19 @@ class FieldEditLine : FrameLayout {
}
fun setEnableAnimation(value: Boolean) {
mEnableAnimation = value
enableAnimation = value
}
var name: String?
get() = mName
get() = _name
set(name) {
mName = name
_name = name
editText.contentDescription = name
mLabel.text = name
label.text = name
}
val lastViewInTabOrder: View
get() = mExpandButton
get() = expandButton
fun loadState(state: AbsSavedState) {
onRestoreInstanceState(state)
@ -175,11 +178,11 @@ class FieldEditLine : FrameLayout {
savedState.editTextId = editText.id
savedState.toggleStickyId = toggleSticky.id
savedState.mediaButtonId = mediaButton.id
savedState.expandButtonId = mExpandButton.id
savedState.expandButtonId = expandButton.id
for (i in 0 until childCount) {
getChildAt(i).saveHierarchyState(savedState.childrenStates)
}
savedState.expansionState = mExpansionState
savedState.expansionState = expansionState
return savedState
}
@ -191,11 +194,11 @@ class FieldEditLine : FrameLayout {
val editTextId = editText.id
val toggleStickyId = toggleSticky.id
val mediaButtonId = mediaButton.id
val expandButtonId = mExpandButton.id
val expandButtonId = expandButton.id
editText.id = state.editTextId
toggleSticky.id = state.toggleStickyId
mediaButton.id = state.mediaButtonId
mExpandButton.id = state.expandButtonId
expandButton.id = state.expandButtonId
super.onRestoreInstanceState(state.superState)
for (i in 0 until childCount) {
getChildAt(i).restoreHierarchyState(state.childrenStates)
@ -203,11 +206,11 @@ class FieldEditLine : FrameLayout {
editText.id = editTextId
toggleSticky.id = toggleStickyId
mediaButton.id = mediaButtonId
mExpandButton.id = expandButtonId
if (mExpansionState != state.expansionState) {
expandButton.id = expandButtonId
if (expansionState != state.expansionState) {
toggleExpansionState()
}
mExpansionState = state.expansionState ?: ExpansionState.EXPANDED
expansionState = state.expansionState ?: ExpansionState.EXPANDED
}
@KotlinCleanup("convert to parcelable")

View File

@ -42,30 +42,30 @@ import timber.log.Timber
*/
class Previewer : AbstractFlashcardViewer() {
private lateinit var mCardList: LongArray
private var mIndex = 0
private var mShowingAnswer = false
private lateinit var mProgressSeekBar: SeekBar
private lateinit var mProgressText: TextView
private lateinit var cardList: LongArray
private var index = 0
private var showingAnswer = false
private lateinit var progressSeekBar: SeekBar
private lateinit var progressText: TextView
/** Communication with Browser */
private var mReloadRequired = false
private var mNoteChanged = false
private var reloadRequired = false
private var noteChanged = false
private var previewLayout: PreviewLayout? = null
override fun onCreate(savedInstanceState: Bundle?) {
if (showedActivityFailedScreen(savedInstanceState)) {
return
}
super.onCreate(savedInstanceState)
mCardList = requireNotNull(intent.getLongArrayExtra("cardList")) { "'cardList' required" }
mIndex = intent.getIntExtra("index", -1)
cardList = requireNotNull(intent.getLongArrayExtra("cardList")) { "'cardList' required" }
index = intent.getIntExtra("index", -1)
if (savedInstanceState != null) {
mIndex = savedInstanceState.getInt("index", mIndex)
mShowingAnswer = savedInstanceState.getBoolean("showingAnswer", mShowingAnswer)
mReloadRequired = savedInstanceState.getBoolean("reloadRequired")
mNoteChanged = savedInstanceState.getBoolean("noteChanged")
index = savedInstanceState.getInt("index", index)
showingAnswer = savedInstanceState.getBoolean("showingAnswer", showingAnswer)
reloadRequired = savedInstanceState.getBoolean("reloadRequired")
noteChanged = savedInstanceState.getBoolean("noteChanged")
}
if (mCardList.isEmpty() || mIndex < 0 || mIndex > mCardList.size - 1) {
if (cardList.isEmpty() || index < 0 || index > cardList.size - 1) {
Timber.e("Previewer started with empty card list or invalid index")
finish()
return
@ -79,26 +79,26 @@ class Previewer : AbstractFlashcardViewer() {
}
private fun initPreviewProgress() {
mProgressSeekBar = findViewById(R.id.preview_progress_seek_bar)
mProgressText = findViewById(R.id.preview_progress_text)
progressSeekBar = findViewById(R.id.preview_progress_seek_bar)
progressText = findViewById(R.id.preview_progress_text)
val progressLayout = findViewById<LinearLayout>(R.id.preview_progress_layout)
// Show layout only when the cardList is bigger than 1
if (mCardList.size > 1) {
if (cardList.size > 1) {
progressLayout.visibility = View.VISIBLE
mProgressSeekBar.max = mCardList.size - 1
progressSeekBar.max = cardList.size - 1
setSeekBarListener()
updateProgress()
}
}
private fun setSeekBarListener() {
mProgressSeekBar.setOnSeekBarChangeListener(object : OnSeekBarChangeListener {
progressSeekBar.setOnSeekBarChangeListener(object : OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
if (fromUser) {
mIndex = progress
index = progress
updateProgress()
currentCard = getColUnsafe.getCard(mCardList[mIndex])
currentCard = getColUnsafe.getCard(cardList[index])
displayCardQuestion()
}
}
@ -108,8 +108,8 @@ class Previewer : AbstractFlashcardViewer() {
}
override fun onStopTrackingTouch(seekBar: SeekBar) {
if (mIndex >= 0 && mIndex < mCardList.size) {
currentCard = getColUnsafe.getCard(mCardList[mIndex])
if (index >= 0 && index < cardList.size) {
currentCard = getColUnsafe.getCard(cardList[index])
displayCardQuestion()
}
}
@ -118,9 +118,9 @@ class Previewer : AbstractFlashcardViewer() {
override fun onCollectionLoaded(col: Collection) {
super.onCollectionLoaded(col)
currentCard = col.getCard(mCardList[mIndex])
currentCard = col.getCard(cardList[index])
displayCardQuestion()
if (mShowingAnswer) {
if (showingAnswer) {
displayCardAnswer()
}
showBackIcon()
@ -131,14 +131,14 @@ class Previewer : AbstractFlashcardViewer() {
* This occurs as many cards can be deleted when editing a note (from the Card Template Editor) */
private fun getNextIndex(newCardList: List<Long>): Int {
val validIndices = HashSet(newCardList)
for (i in mIndex downTo 0) {
if (validIndices.contains(mCardList[i])) {
return newCardList.indexOf(mCardList[i])
for (i in index downTo 0) {
if (validIndices.contains(cardList[i])) {
return newCardList.indexOf(cardList[i])
}
}
for (i in mIndex + 1 until validIndices.size) {
if (validIndices.contains(mCardList[i])) {
return newCardList.indexOf(mCardList[i])
for (i in index + 1 until validIndices.size) {
if (validIndices.contains(cardList[i])) {
return newCardList.indexOf(cardList[i])
}
}
throw IllegalStateException("newCardList was empty")
@ -149,7 +149,7 @@ class Previewer : AbstractFlashcardViewer() {
topBarLayout!!.visibility = View.GONE
findViewById<View>(R.id.answer_options_layout).visibility = View.GONE
findViewById<View>(R.id.bottom_area_layout).visibility = View.VISIBLE
previewLayout = PreviewLayout.createAndDisplay(this, mToggleAnswerHandler)
previewLayout = PreviewLayout.createAndDisplay(this, toggleAnswerHandler)
previewLayout!!.setOnNextCard { changePreviewedCard(true) }
previewLayout!!.setOnPreviousCard { changePreviewedCard(false) }
}
@ -173,17 +173,17 @@ class Previewer : AbstractFlashcardViewer() {
}
override fun onSaveInstanceState(outState: Bundle) {
outState.putLongArray("cardList", mCardList)
outState.putInt("index", mIndex)
outState.putBoolean("showingAnswer", mShowingAnswer)
outState.putBoolean("reloadRequired", mReloadRequired)
outState.putBoolean("noteChanged", mNoteChanged)
outState.putLongArray("cardList", cardList)
outState.putInt("index", index)
outState.putBoolean("showingAnswer", showingAnswer)
outState.putBoolean("reloadRequired", reloadRequired)
outState.putBoolean("noteChanged", noteChanged)
super.onSaveInstanceState(outState)
}
override fun displayCardQuestion() {
super.displayCardQuestion()
mShowingAnswer = false
showingAnswer = false
updateButtonsState()
}
@ -191,7 +191,7 @@ class Previewer : AbstractFlashcardViewer() {
@VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
override fun displayCardAnswer() {
super.displayCardAnswer()
mShowingAnswer = true
showingAnswer = true
updateButtonsState()
}
@ -209,35 +209,35 @@ class Previewer : AbstractFlashcardViewer() {
}
override fun performReload() {
mReloadRequired = true
reloadRequired = true
setOkResult()
val newCardList = getColUnsafe.filterToValidCards(mCardList)
val newCardList = getColUnsafe.filterToValidCards(cardList)
if (newCardList.isEmpty()) {
finish()
return
}
mIndex = getNextIndex(newCardList)
mCardList = newCardList.toLongArray()
currentCard = getColUnsafe.getCard(mCardList[mIndex])
index = getNextIndex(newCardList)
cardList = newCardList.toLongArray()
currentCard = getColUnsafe.getCard(cardList[index])
displayCardQuestion()
}
override fun onEditedNoteChanged() {
super.onEditedNoteChanged()
mNoteChanged = true
noteChanged = true
setOkResult()
}
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
internal fun changePreviewedCard(nextCard: Boolean) {
mIndex = if (nextCard) mIndex + 1 else mIndex - 1
currentCard = getColUnsafe.getCard(mCardList[mIndex])
index = if (nextCard) index + 1 else index - 1
currentCard = getColUnsafe.getCard(cardList[index])
displayCardQuestion()
updateProgress()
}
private val mToggleAnswerHandler = View.OnClickListener {
if (mShowingAnswer) {
private val toggleAnswerHandler = View.OnClickListener {
if (showingAnswer) {
displayCardQuestion()
} else {
displayCardAnswer()
@ -245,32 +245,32 @@ class Previewer : AbstractFlashcardViewer() {
}
private fun updateButtonsState() {
previewLayout!!.setShowingAnswer(mShowingAnswer)
previewLayout!!.setShowingAnswer(showingAnswer)
// If we are in single-card mode, we show the "Show Answer" button on the question side
// and hide navigation buttons.
if (mCardList.size == 1) {
if (cardList.size == 1) {
previewLayout!!.hideNavigationButtons()
return
}
previewLayout!!.setPrevButtonEnabled(mIndex > 0)
previewLayout!!.setNextButtonEnabled(mIndex < mCardList.size - 1)
previewLayout!!.setPrevButtonEnabled(index > 0)
previewLayout!!.setNextButtonEnabled(index < cardList.size - 1)
}
private fun updateProgress() {
if (mProgressSeekBar.progress != mIndex) {
mProgressSeekBar.progress = mIndex
if (progressSeekBar.progress != index) {
progressSeekBar.progress = index
}
val progress = getString(R.string.preview_progress_bar_text, mIndex + 1, mCardList.size)
mProgressText.text = progress
val progress = getString(R.string.preview_progress_bar_text, index + 1, cardList.size)
progressText.text = progress
}
private fun setOkResult() {
setResult(
RESULT_OK,
Intent().apply {
putExtra("reloadRequired", mReloadRequired)
putExtra("noteChanged", mNoteChanged)
putExtra("reloadRequired", reloadRequired)
putExtra("noteChanged", noteChanged)
}
)
}

View File

@ -105,10 +105,10 @@ open class Reviewer :
PostRequestHandler {
private var queueState: CurrentQueueState? = null
private val customSchedulingKey = TimeManager.time.intTimeMS().toString()
private var mHasDrawerSwipeConflicts = false
private var mShowWhiteboard = true
private var mPrefFullscreenReview = false
private lateinit var mColorPalette: LinearLayout
private var hasDrawerSwipeConflicts = false
private var showWhiteboard = true
private var prefFullscreenReview = false
private lateinit var colorPalette: LinearLayout
private var toggleStylus = false
private val server = AnkiServer(this).also { it.start() }
@ -134,14 +134,14 @@ open class Reviewer :
// TODO: Consider extracting to ViewModel
// Card counts
private var mNewCount: SpannableString? = null
private var mLrnCount: SpannableString? = null
private var mRevCount: SpannableString? = null
private lateinit var mTextBarNew: TextView
private lateinit var mTextBarLearn: TextView
private lateinit var mTextBarReview: TextView
private var newCount: SpannableString? = null
private var lrnCount: SpannableString? = null
private var revCount: SpannableString? = null
private lateinit var textBarNew: TextView
private lateinit var textBarLearn: TextView
private lateinit var textBarReview: TextView
private lateinit var answerTimer: AnswerTimer
private var mPrefHideDueCount = false
private var prefHideDueCount = false
// Whiteboard
var prefWhiteboard = false
@ -158,21 +158,21 @@ open class Reviewer :
private lateinit var micToolBarLayer: LinearLayout
// ETA
private var mEta = 0
private var eta = 0
/** Handle Mark/Flag state of cards */
@VisibleForTesting
internal var mCardMarker: CardMarker? = null
internal var cardMarker: CardMarker? = null
// Preferences from the collection
private var mShowRemainingCardCount = false
private var showRemainingCardCount = false
private var stopTimerOnAnswer = false
private val mActionButtons = ActionButtons()
private lateinit var mToolbar: Toolbar
private val actionButtons = ActionButtons()
private lateinit var toolbar: Toolbar
@VisibleForTesting
protected val mProcessor = PeripheralKeymap(this, this)
private val mOnboarding = Onboarding.Reviewer(this)
protected val processor = PeripheralKeymap(this, this)
private val onboarding = Onboarding.Reviewer(this)
private val addNoteLauncher = registerForActivityResult(
ActivityResultContracts.StartActivityForResult(),
@ -189,12 +189,12 @@ open class Reviewer :
finish()
return
}
mColorPalette = findViewById(R.id.whiteboard_editor)
colorPalette = findViewById(R.id.whiteboard_editor)
answerTimer = AnswerTimer(findViewById(R.id.card_time))
mTextBarNew = findViewById(R.id.new_number)
mTextBarLearn = findViewById(R.id.learn_number)
mTextBarReview = findViewById(R.id.review_number)
mToolbar = findViewById(R.id.toolbar)
textBarNew = findViewById(R.id.new_number)
textBarLearn = findViewById(R.id.learn_number)
textBarReview = findViewById(R.id.review_number)
toolbar = findViewById(R.id.toolbar)
micToolBarLayer = findViewById(R.id.mic_tool_bar_layer)
startLoadingCollection()
@ -225,8 +225,8 @@ open class Reviewer :
get() {
return FlagToDisplay(
currentCard!!.userFlag(),
mActionButtons.findMenuItem(ActionButtons.RES_FLAG)?.isActionButton ?: true,
mPrefFullscreenReview
actionButtons.findMenuItem(ActionButtons.RES_FLAG)?.isActionButton ?: true,
prefFullscreenReview
).get()
}
@ -245,8 +245,8 @@ open class Reviewer :
}
// If we don't know: assume it's not shown
val shownAsToolbarButton = mActionButtons.findMenuItem(ActionButtons.RES_MARK)?.isActionButton == true
return !shownAsToolbarButton || mPrefFullscreenReview
val shownAsToolbarButton = actionButtons.findMenuItem(ActionButtons.RES_MARK)?.isActionButton == true
return !shownAsToolbarButton || prefFullscreenReview
}
protected open fun onMark(card: Card?) {
@ -264,7 +264,7 @@ open class Reviewer :
if (currentCard == null) {
return
}
mCardMarker!!.displayMark(shouldDisplayMark())
cardMarker!!.displayMark(shouldDisplayMark())
}
protected open fun onFlag(card: Card?, flag: Flag) {
@ -285,7 +285,7 @@ open class Reviewer :
if (currentCard == null) {
return
}
mCardMarker!!.displayFlag(Flag.fromCode(flagToDisplay))
cardMarker!!.displayFlag(Flag.fromCode(flagToDisplay))
}
private fun selectDeckFromExtra() {
@ -343,7 +343,7 @@ open class Reviewer :
disableDrawerSwipeOnConflicts()
// Set full screen/immersive mode if needed
if (mPrefFullscreenReview) {
if (prefFullscreenReview) {
setFullScreen(this)
}
setRenderWorkaround(this)
@ -366,7 +366,7 @@ open class Reviewer :
}
R.id.action_undo -> {
Timber.i("Reviewer:: Undo button pressed")
if (mShowWhiteboard && whiteboard != null && !whiteboard!!.undoEmpty()) {
if (showWhiteboard && whiteboard != null && !whiteboard!!.undoEmpty()) {
whiteboard!!.undo()
} else {
undo()
@ -432,8 +432,8 @@ open class Reviewer :
clearWhiteboard()
}
R.id.action_hide_whiteboard -> { // toggle whiteboard visibility
Timber.i("Reviewer:: Whiteboard visibility set to %b", !mShowWhiteboard)
setWhiteboardVisibility(!mShowWhiteboard)
Timber.i("Reviewer:: Whiteboard visibility set to %b", !showWhiteboard)
setWhiteboardVisibility(!showWhiteboard)
refreshActionBar()
}
R.id.action_toggle_stylus -> { // toggle stylus mode
@ -509,7 +509,7 @@ open class Reviewer :
setWhiteboardEnabledState(prefWhiteboard)
setWhiteboardVisibility(prefWhiteboard)
if (!prefWhiteboard) {
mColorPalette.visibility = View.GONE
colorPalette.visibility = View.GONE
}
refreshActionBar()
}
@ -521,10 +521,10 @@ open class Reviewer :
}
public override fun changeWhiteboardPenColor() {
if (mColorPalette.visibility == View.GONE) {
mColorPalette.visibility = View.VISIBLE
if (colorPalette.visibility == View.GONE) {
colorPalette.visibility = View.VISIBLE
} else {
mColorPalette.visibility = View.GONE
colorPalette.visibility = View.GONE
}
updateWhiteboardEditorPosition()
}
@ -704,7 +704,7 @@ open class Reviewer :
// NOTE: This is called every time a new question is shown via invalidate options menu
menuInflater.inflate(R.menu.reviewer, menu)
displayIcons(menu)
mActionButtons.setCustomButtonsStatus(menu)
actionButtons.setCustomButtonsStatus(menu)
val alpha = Themes.ALPHA_ICON_ENABLED_LIGHT
val markCardIcon = menu.findItem(R.id.action_mark_card)
if (currentCard != null && isMarked(currentCard!!.note())) {
@ -734,7 +734,7 @@ open class Reviewer :
// Undo button
@DrawableRes val undoIconId: Int
val undoEnabled: Boolean
val whiteboardIsShownAndHasStrokes = mShowWhiteboard && whiteboard?.undoEmpty() == false
val whiteboardIsShownAndHasStrokes = showWhiteboard && whiteboard?.undoEmpty() == false
if (whiteboardIsShownAndHasStrokes) {
undoIconId = R.drawable.eraser
undoEnabled = true
@ -772,7 +772,7 @@ open class Reviewer :
}
}
if (undoEnabled) {
mOnboarding.onUndoButtonEnabled()
onboarding.onUndoButtonEnabled()
}
val toggleWhiteboardIcon = menu.findItem(R.id.action_toggle_whiteboard)
val toggleStylusIcon = menu.findItem(R.id.action_toggle_stylus)
@ -784,25 +784,25 @@ open class Reviewer :
toggleWhiteboardIcon.setTitle(R.string.disable_whiteboard)
// Always allow "Disable Whiteboard", even if "Enable Whiteboard" is disabled
toggleWhiteboardIcon.isVisible = true
if (!mActionButtons.status.toggleStylusIsDisabled()) {
if (!actionButtons.status.toggleStylusIsDisabled()) {
toggleStylusIcon.isVisible = true
}
if (!mActionButtons.status.hideWhiteboardIsDisabled()) {
if (!actionButtons.status.hideWhiteboardIsDisabled()) {
hideWhiteboardIcon.isVisible = true
}
if (!mActionButtons.status.clearWhiteboardIsDisabled()) {
if (!actionButtons.status.clearWhiteboardIsDisabled()) {
menu.findItem(R.id.action_clear_whiteboard).isVisible = true
}
if (!mActionButtons.status.saveWhiteboardIsDisabled()) {
if (!actionButtons.status.saveWhiteboardIsDisabled()) {
menu.findItem(R.id.action_save_whiteboard).isVisible = true
}
if (!mActionButtons.status.whiteboardPenColorIsDisabled()) {
if (!actionButtons.status.whiteboardPenColorIsDisabled()) {
changePenColorIcon.isVisible = true
}
val whiteboardIcon = ContextCompat.getDrawable(this, R.drawable.ic_gesture_white)!!.mutate()
val stylusIcon = ContextCompat.getDrawable(this, R.drawable.ic_gesture_stylus)!!.mutate()
val whiteboardColorPaletteIcon = VectorDrawableCompat.create(resources, R.drawable.ic_color_lens_white_24dp, this.theme)!!.mutate()
if (mShowWhiteboard) {
if (showWhiteboard) {
whiteboardIcon.alpha = Themes.ALPHA_ICON_ENABLED_LIGHT
hideWhiteboardIcon.icon = whiteboardIcon
hideWhiteboardIcon.setTitle(R.string.hide_whiteboard)
@ -826,7 +826,7 @@ open class Reviewer :
toggleStylusIcon.icon = stylusIcon
changePenColorIcon.isEnabled = false
changePenColorIcon.icon = whiteboardColorPaletteIcon
mColorPalette.visibility = View.GONE
colorPalette.visibility = View.GONE
}
} else {
toggleWhiteboardIcon.setTitle(R.string.enable_whiteboard)
@ -834,19 +834,19 @@ open class Reviewer :
if (colIsOpenUnsafe() && getColUnsafe.decks.isDyn(parentDid)) {
menu.findItem(R.id.action_open_deck_options).isVisible = false
}
if (mTTS.enabled && !mActionButtons.status.selectTtsIsDisabled()) {
if (tts.enabled && !actionButtons.status.selectTtsIsDisabled()) {
menu.findItem(R.id.action_select_tts).isVisible = true
}
if (!suspendNoteAvailable() && !mActionButtons.status.suspendIsDisabled()) {
if (!suspendNoteAvailable() && !actionButtons.status.suspendIsDisabled()) {
menu.findItem(R.id.action_suspend).isVisible = false
menu.findItem(R.id.action_suspend_card).isVisible = true
}
if (!buryNoteAvailable() && !mActionButtons.status.buryIsDisabled()) {
if (!buryNoteAvailable() && !actionButtons.status.buryIsDisabled()) {
menu.findItem(R.id.action_bury).isVisible = false
menu.findItem(R.id.action_bury_card).isVisible = true
}
mOnboarding.onCreate()
onboarding.onCreate()
increaseHorizontalPaddingOfOverflowMenuIcons(menu)
tintOverflowMenuIcons(menu, skipIf = { isFlagResource(it.itemId) })
@ -875,14 +875,14 @@ open class Reviewer :
if (answerFieldIsFocused()) {
return super.onKeyDown(keyCode, event)
}
if (mProcessor.onKeyDown(keyCode, event) || super.onKeyDown(keyCode, event)) {
if (processor.onKeyDown(keyCode, event) || super.onKeyDown(keyCode, event)) {
return true
}
return false
}
override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean {
return if (mProcessor.onKeyUp(keyCode, event)) {
return if (processor.onKeyUp(keyCode, event)) {
true
} else {
super.onKeyUp(keyCode, event)
@ -906,7 +906,7 @@ open class Reviewer :
override fun displayAnswerBottomBar() {
super.displayAnswerBottomBar()
mOnboarding.onAnswerShown()
onboarding.onAnswerShown()
// Set correct label and background resource for each button
// Note that it's necessary to set the resource dynamically as the ease2 / ease3 buttons
// (which libanki expects ease to be 2 and 3) can either be hard, good, or easy - depending on num buttons shown
@ -945,10 +945,10 @@ open class Reviewer :
override fun restorePreferences(): SharedPreferences {
val preferences = super.restorePreferences()
mPrefHideDueCount = preferences.getBoolean("hideDueCount", false)
mProcessor.setup()
mPrefFullscreenReview = isFullScreenReview(preferences)
mActionButtons.setup(preferences)
prefHideDueCount = preferences.getBoolean("hideDueCount", false)
processor.setup()
prefFullscreenReview = isFullScreenReview(preferences)
actionButtons.setup(preferences)
return preferences
}
@ -958,22 +958,22 @@ open class Reviewer :
}
private fun updateWhiteboardEditorPosition() {
mAnswerButtonsPosition = this.sharedPrefs()
answerButtonsPosition = this.sharedPrefs()
.getString("answerButtonPosition", "bottom")
val layoutParams: RelativeLayout.LayoutParams
when (mAnswerButtonsPosition) {
when (answerButtonsPosition) {
"none", "top" -> {
layoutParams = mColorPalette.layoutParams as RelativeLayout.LayoutParams
layoutParams = colorPalette.layoutParams as RelativeLayout.LayoutParams
layoutParams.removeRule(RelativeLayout.ABOVE)
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM)
mColorPalette.layoutParams = layoutParams
colorPalette.layoutParams = layoutParams
}
"bottom" -> {
layoutParams = mColorPalette.layoutParams as RelativeLayout.LayoutParams
layoutParams = colorPalette.layoutParams as RelativeLayout.LayoutParams
layoutParams.removeRule(RelativeLayout.ALIGN_PARENT_BOTTOM)
layoutParams.addRule(RelativeLayout.ABOVE, R.id.bottom_area_layout)
mColorPalette.layoutParams = layoutParams
colorPalette.layoutParams = layoutParams
}
}
}
@ -982,29 +982,29 @@ open class Reviewer :
val queue = queueState ?: return
super.updateActionBar()
val counts = queue.counts
mNewCount = SpannableString(counts.new.toString())
mLrnCount = SpannableString(counts.lrn.toString())
mRevCount = SpannableString(counts.rev.toString())
if (mPrefHideDueCount) {
mRevCount = SpannableString("???")
newCount = SpannableString(counts.new.toString())
lrnCount = SpannableString(counts.lrn.toString())
revCount = SpannableString(counts.rev.toString())
if (prefHideDueCount) {
revCount = SpannableString("???")
}
// if this code is run as a card is being answered, currentCard may be non-null but
// the queues may be empty - we can't call countIdx() in such a case
if (counts.count() != 0) {
when (queue.countsIndex) {
Counts.Queue.NEW -> mNewCount!!.setSpan(UnderlineSpan(), 0, mNewCount!!.length, 0)
Counts.Queue.LRN -> mLrnCount!!.setSpan(UnderlineSpan(), 0, mLrnCount!!.length, 0)
Counts.Queue.REV -> mRevCount!!.setSpan(UnderlineSpan(), 0, mRevCount!!.length, 0)
Counts.Queue.NEW -> newCount!!.setSpan(UnderlineSpan(), 0, newCount!!.length, 0)
Counts.Queue.LRN -> lrnCount!!.setSpan(UnderlineSpan(), 0, lrnCount!!.length, 0)
Counts.Queue.REV -> revCount!!.setSpan(UnderlineSpan(), 0, revCount!!.length, 0)
}
}
mTextBarNew.text = mNewCount
mTextBarLearn.text = mLrnCount
mTextBarReview.text = mRevCount
textBarNew.text = newCount
textBarLearn.text = lrnCount
textBarReview.text = revCount
}
override fun fillFlashcard() {
super.fillFlashcard()
if (!isDisplayingAnswer && mShowWhiteboard && whiteboard != null) {
if (!isDisplayingAnswer && showWhiteboard && whiteboard != null) {
whiteboard!!.clear()
}
}
@ -1121,25 +1121,25 @@ open class Reviewer :
override fun initLayout() {
super.initLayout()
if (!mShowRemainingCardCount) {
mTextBarNew.visibility = View.GONE
mTextBarLearn.visibility = View.GONE
mTextBarReview.visibility = View.GONE
if (!showRemainingCardCount) {
textBarNew.visibility = View.GONE
textBarLearn.visibility = View.GONE
textBarReview.visibility = View.GONE
}
// can't move this into onCreate due to mTopBarLayout
val mark = topBarLayout!!.findViewById<ImageView>(R.id.mark_icon)
val flag = topBarLayout!!.findViewById<ImageView>(R.id.flag_icon)
mCardMarker = CardMarker(mark, flag)
cardMarker = CardMarker(mark, flag)
}
override fun switchTopBarVisibility(visible: Int) {
super.switchTopBarVisibility(visible)
answerTimer.setVisibility(visible)
if (mShowRemainingCardCount) {
mTextBarNew.visibility = visible
mTextBarLearn.visibility = visible
mTextBarReview.visibility = visible
if (showRemainingCardCount) {
textBarNew.visibility = visible
textBarLearn.visibility = visible
textBarReview.visibility = visible
}
}
@ -1153,12 +1153,12 @@ open class Reviewer :
override fun initControls() {
super.initControls()
if (prefWhiteboard) {
setWhiteboardVisibility(mShowWhiteboard)
setWhiteboardVisibility(showWhiteboard)
}
if (mShowRemainingCardCount) {
mTextBarNew.visibility = View.VISIBLE
mTextBarLearn.visibility = View.VISIBLE
mTextBarReview.visibility = View.VISIBLE
if (showRemainingCardCount) {
textBarNew.visibility = View.VISIBLE
textBarLearn.visibility = View.VISIBLE
textBarReview.visibility = View.VISIBLE
}
}
@ -1232,12 +1232,12 @@ open class Reviewer :
override fun restoreCollectionPreferences(col: Collection) {
super.restoreCollectionPreferences(col)
mShowRemainingCardCount = col.config.get("dueCounts") ?: true
showRemainingCardCount = col.config.get("dueCounts") ?: true
stopTimerOnAnswer = col.decks.confForDid(col.decks.current().id).getBoolean("stopTimerOnAnswer")
}
override fun onSingleTap(): Boolean {
if (mPrefFullscreenReview && isImmersiveSystemUiVisible(this)) {
if (prefFullscreenReview && isImmersiveSystemUiVisible(this)) {
delayedHide(INITIAL_HIDE_DELAY)
return true
}
@ -1245,7 +1245,7 @@ open class Reviewer :
}
override fun onFling() {
if (mPrefFullscreenReview && isImmersiveSystemUiVisible(this)) {
if (prefFullscreenReview && isImmersiveSystemUiVisible(this)) {
delayedHide(INITIAL_HIDE_DELAY)
}
}
@ -1262,9 +1262,9 @@ open class Reviewer :
}
}
private val mFullScreenHandler: Handler = object : Handler(getDefaultLooper()) {
private val fullScreenHandler: Handler = object : Handler(getDefaultLooper()) {
override fun handleMessage(msg: Message) {
if (mPrefFullscreenReview) {
if (prefFullscreenReview) {
setFullScreen(this@Reviewer)
}
}
@ -1273,8 +1273,8 @@ open class Reviewer :
/** Hide the navigation if in full-screen mode after a given period of time */
protected open fun delayedHide(delayMillis: Int) {
Timber.d("Fullscreen delayed hide in %dms", delayMillis)
mFullScreenHandler.removeMessages(0)
mFullScreenHandler.sendEmptyMessageDelayed(0, delayMillis.toLong())
fullScreenHandler.removeMessages(0)
fullScreenHandler.sendEmptyMessageDelayed(0, delayMillis.toLong())
}
private fun setWhiteboardEnabledState(state: Boolean) {
@ -1409,8 +1409,8 @@ open class Reviewer :
if (event == null) return@setOnTouchListener false
// If the whiteboard is currently drawing, and triggers the system UI to show, we want to continue drawing.
if (!whiteboard!!.isCurrentlyDrawing && (
!mShowWhiteboard || (
mPrefFullscreenReview &&
!showWhiteboard || (
prefFullscreenReview &&
isImmersiveSystemUiVisible(this@Reviewer)
)
)
@ -1425,22 +1425,22 @@ open class Reviewer :
// Show or hide the whiteboard
private fun setWhiteboardVisibility(state: Boolean) {
mShowWhiteboard = state
showWhiteboard = state
MetaDB.storeWhiteboardVisibility(this, parentDid, state)
if (state) {
whiteboard!!.visibility = View.VISIBLE
disableDrawerSwipe()
} else {
whiteboard!!.visibility = View.GONE
if (!mHasDrawerSwipeConflicts) {
if (!hasDrawerSwipeConflicts) {
enableDrawerSwipe()
}
}
}
private fun disableDrawerSwipeOnConflicts() {
if (mGestureProcessor.isBound(Gesture.SWIPE_UP, Gesture.SWIPE_DOWN, Gesture.SWIPE_RIGHT)) {
mHasDrawerSwipeConflicts = true
if (gestureProcessor.isBound(Gesture.SWIPE_UP, Gesture.SWIPE_DOWN, Gesture.SWIPE_RIGHT)) {
hasDrawerSwipeConflicts = true
super.disableDrawerSwipe()
}
}
@ -1454,7 +1454,7 @@ open class Reviewer :
if (hasFocus) {
delayedHide(INITIAL_HIDE_DELAY)
} else {
mFullScreenHandler.removeMessages(0)
fullScreenHandler.removeMessages(0)
}
}
@ -1492,19 +1492,19 @@ open class Reviewer :
@VisibleForTesting(otherwise = VisibleForTesting.NONE)
fun hasDrawerSwipeConflicts(): Boolean {
return mHasDrawerSwipeConflicts
return hasDrawerSwipeConflicts
}
override fun getCardDataForJsApi(): AnkiDroidJsAPI.CardDataForJsApi {
val cardDataForJsAPI = AnkiDroidJsAPI.CardDataForJsApi().apply {
newCardCount = mNewCount.toString()
lrnCardCount = mLrnCount.toString()
revCardCount = mRevCount.toString()
newCardCount = newCount.toString()
lrnCardCount = lrnCount.toString()
revCardCount = revCount.toString()
nextTime1 = easeButton1!!.nextTime
nextTime2 = easeButton2!!.nextTime
nextTime3 = easeButton3!!.nextTime
nextTime4 = easeButton4!!.nextTime
eta = mEta
eta = this@Reviewer.eta
}
return cardDataForJsAPI
}

View File

@ -52,19 +52,19 @@ import kotlin.math.abs
*/
class SharedDecksDownloadFragment : Fragment() {
private var mDownloadId: Long = 0
private var downloadId: Long = 0
private var mFileName: String? = null
private var fileName: String? = null
private var mHandler: Handler = Handler(Looper.getMainLooper())
private var mIsProgressCheckerRunning = false
private var handler: Handler = Handler(Looper.getMainLooper())
private var isProgressCheckerRunning = false
private lateinit var mCancelButton: Button
private lateinit var mTryAgainButton: Button
private lateinit var mImportDeckButton: Button
private lateinit var mDownloadPercentageText: TextView
private lateinit var mDownloadProgressBar: ProgressBar
private lateinit var mCheckNetworkInfoText: TextView
private lateinit var cancelButton: Button
private lateinit var tryAgainButton: Button
private lateinit var importDeckButton: Button
private lateinit var downloadPercentageText: TextView
private lateinit var downloadProgressBar: ProgressBar
private lateinit var checkNetworkInfoText: TextView
/**
* Android's DownloadManager - Used here to manage the functionality of downloading decks, one
@ -73,7 +73,7 @@ class SharedDecksDownloadFragment : Fragment() {
* Since only one download is supported at a time, the DownloadManager's queue is expected to
* have a single request at a time.
*/
private lateinit var mDownloadManager: DownloadManager
private lateinit var downloadManager: DownloadManager
var isDownloadInProgress = false
@ -108,34 +108,34 @@ class SharedDecksDownloadFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
mDownloadPercentageText = view.findViewById(R.id.download_percentage)
mDownloadProgressBar = view.findViewById(R.id.download_progress)
mCancelButton = view.findViewById(R.id.cancel_shared_decks_download)
mImportDeckButton = view.findViewById(R.id.import_shared_deck_button)
mTryAgainButton = view.findViewById(R.id.try_again_deck_download)
mCheckNetworkInfoText = view.findViewById(R.id.check_network_info_text)
downloadPercentageText = view.findViewById(R.id.download_percentage)
downloadProgressBar = view.findViewById(R.id.download_progress)
cancelButton = view.findViewById(R.id.cancel_shared_decks_download)
importDeckButton = view.findViewById(R.id.import_shared_deck_button)
tryAgainButton = view.findViewById(R.id.try_again_deck_download)
checkNetworkInfoText = view.findViewById(R.id.check_network_info_text)
val fileToBeDownloaded = arguments?.getSerializableCompat<DownloadFile>(DOWNLOAD_FILE)!!
mDownloadManager = (activity as SharedDecksActivity).downloadManager
downloadManager = (activity as SharedDecksActivity).downloadManager
downloadFile(fileToBeDownloaded)
mCancelButton.setOnClickListener {
cancelButton.setOnClickListener {
Timber.i("Cancel download button clicked which would lead to showing of confirmation dialog")
showCancelConfirmationDialog()
}
mImportDeckButton.setOnClickListener {
importDeckButton.setOnClickListener {
Timber.i("Import deck button clicked")
openDownloadedDeck(context)
}
mTryAgainButton.setOnClickListener {
tryAgainButton.setOnClickListener {
Timber.i("Try again button clicked, retry downloading of deck")
mDownloadManager.remove(mDownloadId)
downloadManager.remove(downloadId)
downloadFile(fileToBeDownloaded)
mCancelButton.visibility = View.VISIBLE
mTryAgainButton.visibility = View.GONE
cancelButton.visibility = View.VISIBLE
tryAgainButton.visibility = View.GONE
}
}
@ -159,7 +159,7 @@ class SharedDecksDownloadFragment : Fragment() {
}
// Register broadcast receiver for download completion.
Timber.d("Registering broadcast receiver for download completion")
activity?.registerReceiver(mOnComplete, IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE))
activity?.registerReceiver(onComplete, IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE))
val currentFileName = URLUtil.guessFileName(
fileToBeDownloaded.url,
@ -170,12 +170,12 @@ class SharedDecksDownloadFragment : Fragment() {
val downloadRequest = generateDeckDownloadRequest(fileToBeDownloaded, currentFileName)
// Store unique download ID to be used when onReceive() of BroadcastReceiver gets executed.
mDownloadId = mDownloadManager.enqueue(downloadRequest)
mFileName = currentFileName
downloadId = downloadManager.enqueue(downloadRequest)
fileName = currentFileName
isDownloadInProgress = true
Timber.d("Download ID -> $mDownloadId")
Timber.d("File name -> $mFileName")
view?.findViewById<TextView>(R.id.downloading_title)?.text = getString(R.string.downloading_file, mFileName)
Timber.d("Download ID -> $downloadId")
Timber.d("File name -> $fileName")
view?.findViewById<TextView>(R.id.downloading_title)?.text = getString(R.string.downloading_file, fileName)
startDownloadProgressChecker()
}
@ -204,7 +204,7 @@ class SharedDecksDownloadFragment : Fragment() {
* Registered in downloadFile() method.
* When onReceive() is called, open the deck file in AnkiDroid to import it.
*/
private var mOnComplete: BroadcastReceiver = object : BroadcastReceiver() {
private var onComplete: BroadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent?) {
Timber.i("Download might be complete now, verify and continue with import")
@ -212,7 +212,7 @@ class SharedDecksDownloadFragment : Fragment() {
* @return Whether the data in the received data is an importable deck
*/
fun verifyDeckIsImportable(): Boolean {
if (mFileName == null) {
if (fileName == null) {
// Send ACRA report
CrashReportService.sendExceptionReport(
"File name is null",
@ -222,7 +222,7 @@ class SharedDecksDownloadFragment : Fragment() {
}
// Return if mDownloadId does not match with the ID of the completed download.
if (mDownloadId != intent?.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, 0)) {
if (downloadId != intent?.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, 0)) {
Timber.w(
"Download ID did not match with the ID of the completed download. " +
"Download completion related to some other download might have been received. " +
@ -234,15 +234,15 @@ class SharedDecksDownloadFragment : Fragment() {
stopDownloadProgressChecker()
// Halt execution if file doesn't have extension as 'apkg' or 'colpkg'
if (!ImportUtils.isFileAValidDeck(mFileName!!)) {
if (!ImportUtils.isFileAValidDeck(fileName!!)) {
Timber.i("File does not have 'apkg' or 'colpkg' extension, abort the deck opening task")
checkDownloadStatusAndUnregisterReceiver(isSuccessful = false, isInvalidDeckFile = true)
return false
}
val query = DownloadManager.Query()
query.setFilterById(mDownloadId)
val cursor = mDownloadManager.query(query)
query.setFilterById(downloadId)
val cursor = downloadManager.query(query)
cursor.use {
// Return if cursor is empty.
@ -282,12 +282,12 @@ class SharedDecksDownloadFragment : Fragment() {
if (isVisible) {
// Setting these since progress checker can stop before progress is updated to represent 100%
mDownloadPercentageText.text = getString(R.string.percentage, DOWNLOAD_COMPLETED_PROGRESS_PERCENTAGE)
mDownloadProgressBar.progress = DOWNLOAD_COMPLETED_PROGRESS_PERCENTAGE.toInt()
downloadPercentageText.text = getString(R.string.percentage, DOWNLOAD_COMPLETED_PROGRESS_PERCENTAGE)
downloadProgressBar.progress = DOWNLOAD_COMPLETED_PROGRESS_PERCENTAGE.toInt()
// Remove cancel button and show import deck button
mCancelButton.visibility = View.GONE
mImportDeckButton.visibility = View.VISIBLE
cancelButton.visibility = View.GONE
importDeckButton.visibility = View.VISIBLE
}
Timber.i("Opening downloaded deck for import")
@ -304,7 +304,7 @@ class SharedDecksDownloadFragment : Fragment() {
private fun unregisterReceiver() {
Timber.d("Unregistering receiver")
try {
activity?.unregisterReceiver(mOnComplete)
activity?.unregisterReceiver(onComplete)
} catch (exception: IllegalArgumentException) {
// This might throw an exception in cases where the receiver is already in unregistered state.
// Log the exception in such cases, there is nothing else to do.
@ -316,7 +316,7 @@ class SharedDecksDownloadFragment : Fragment() {
/**
* Check download progress and update status at intervals of 0.1 second.
*/
private val mDownloadProgressChecker: Runnable by lazy {
private val downloadProgressChecker: Runnable by lazy {
object : Runnable {
override fun run() {
if (!isVisible) {
@ -326,7 +326,7 @@ class SharedDecksDownloadFragment : Fragment() {
checkDownloadProgress()
// Keep checking download progress at intervals of 1 second.
mHandler.postDelayed(this, DOWNLOAD_PROGRESS_CHECK_DELAY)
handler.postDelayed(this, DOWNLOAD_PROGRESS_CHECK_DELAY)
}
}
}
@ -336,10 +336,10 @@ class SharedDecksDownloadFragment : Fragment() {
*/
private fun startDownloadProgressChecker() {
Timber.d("Starting download progress checker")
mDownloadProgressChecker.run()
mIsProgressCheckerRunning = true
mDownloadPercentageText.text = getString(R.string.percentage, DOWNLOAD_STARTED_PROGRESS_PERCENTAGE)
mDownloadProgressBar.progress = DOWNLOAD_STARTED_PROGRESS_PERCENTAGE.toInt()
downloadProgressChecker.run()
isProgressCheckerRunning = true
downloadPercentageText.text = getString(R.string.percentage, DOWNLOAD_STARTED_PROGRESS_PERCENTAGE)
downloadProgressBar.progress = DOWNLOAD_STARTED_PROGRESS_PERCENTAGE.toInt()
}
/**
@ -347,8 +347,8 @@ class SharedDecksDownloadFragment : Fragment() {
*/
private fun stopDownloadProgressChecker() {
Timber.d("Stopping download progress checker")
mHandler.removeCallbacks(mDownloadProgressChecker)
mIsProgressCheckerRunning = false
handler.removeCallbacks(downloadProgressChecker)
isProgressCheckerRunning = false
}
/**
@ -356,9 +356,9 @@ class SharedDecksDownloadFragment : Fragment() {
*/
private fun checkDownloadProgress() {
val query = DownloadManager.Query()
query.setFilterById(mDownloadId)
query.setFilterById(downloadId)
val cursor = mDownloadManager.query(query)
val cursor = downloadManager.query(query)
cursor.use {
// Return if cursor is empty.
@ -379,8 +379,8 @@ class SharedDecksDownloadFragment : Fragment() {
// Show download progress percentage up to 1 decimal place.
"%.1f".format(downloadProgress)
}
mDownloadPercentageText.text = getString(R.string.percentage, percentageValue)
mDownloadProgressBar.progress = downloadProgress.toInt()
downloadPercentageText.text = getString(R.string.percentage, percentageValue)
downloadProgressBar.progress = downloadProgress.toInt()
val columnIndexForStatus = it.getColumnIndex(DownloadManager.COLUMN_STATUS)
val columnIndexForReason = it.getColumnIndex(DownloadManager.COLUMN_REASON)
@ -399,9 +399,9 @@ class SharedDecksDownloadFragment : Fragment() {
if (it.getInt(columnIndexForStatus) == DownloadManager.STATUS_PAUSED &&
it.getInt(columnIndexForReason) == DownloadManager.PAUSED_WAITING_FOR_NETWORK
) {
mCheckNetworkInfoText.visibility = View.VISIBLE
checkNetworkInfoText.visibility = View.VISIBLE
} else {
mCheckNetworkInfoText.visibility = View.GONE
checkNetworkInfoText.visibility = View.GONE
}
}
}
@ -410,7 +410,7 @@ class SharedDecksDownloadFragment : Fragment() {
* Open the downloaded deck using 'mFileName'.
*/
private fun openDownloadedDeck(context: Context?) {
val mimeType = URLConnection.guessContentTypeFromName(mFileName)
val mimeType = URLConnection.guessContentTypeFromName(fileName)
val fileIntent = Intent(context, IntentHandler::class.java)
fileIntent.action = Intent.ACTION_VIEW
@ -419,7 +419,7 @@ class SharedDecksDownloadFragment : Fragment() {
FileProvider.getUriForFile(
it,
it.applicationContext?.packageName + ".apkgfileprovider",
File(sharedDecksPath, mFileName.toString())
File(sharedDecksPath, fileName.toString())
)
}
Timber.d("File URI -> $fileUri")
@ -452,10 +452,10 @@ class SharedDecksDownloadFragment : Fragment() {
Timber.i("Download failed, update UI and provide option to retry")
context?.let { UIUtils.showThemedToast(it, R.string.something_wrong, false) }
// Update UI if download could not be successful
mTryAgainButton.visibility = View.VISIBLE
mCancelButton.visibility = View.GONE
mDownloadPercentageText.text = getString(R.string.download_failed)
mDownloadProgressBar.progress = DOWNLOAD_STARTED_PROGRESS_PERCENTAGE.toInt()
tryAgainButton.visibility = View.VISIBLE
cancelButton.visibility = View.GONE
downloadPercentageText.text = getString(R.string.download_failed)
downloadProgressBar.progress = DOWNLOAD_STARTED_PROGRESS_PERCENTAGE.toInt()
}
}
@ -471,7 +471,7 @@ class SharedDecksDownloadFragment : Fragment() {
downloadCancelConfirmationDialog = AlertDialog.Builder(requireContext()).apply {
setTitle(R.string.cancel_download_question_title)
setPositiveButton(R.string.dialog_yes) { _, _ ->
mDownloadManager.remove(mDownloadId)
downloadManager.remove(downloadId)
unregisterReceiver()
isDownloadInProgress = false
activity?.onBackPressed()

View File

@ -406,7 +406,7 @@ class MigrateStorageOnSyncSuccess(res: Resources) : AsyncOperation() {
* @param messageResource String resource for message
*/
fun DeckPicker.showSyncLogMessage(@StringRes messageResource: Int, syncMessage: String?) {
if (mActivityPaused) {
if (activityPaused) {
val res = AnkiDroidApp.appResources
showSimpleNotification(
res.getString(R.string.app_name),

View File

@ -66,7 +66,7 @@ class ExportReadyDialog(private val listener: ExportReadyDialogListener) : Async
) {
override fun handleAsyncMessage(deckPicker: DeckPicker) {
deckPicker.showDialogFragment(
deckPicker.mExportingDelegate.mDialogsFactory.newExportReadyDialog().withArguments(exportPath)
deckPicker.exportingDelegate.dialogsFactory.newExportReadyDialog().withArguments(exportPath)
)
}

View File

@ -53,7 +53,7 @@ class RecursivePictureMenu : DialogFragment() {
val item = items[position]
textView.setText(item.title)
textView.setOnClickListener { item.execute(requireActivity() as AnkiActivity) }
val icon = item.mIcon
val icon = item.icon
textView.setCompoundDrawablesRelativeWithIntrinsicBounds(icon, 0, 0, 0)
}
@ -73,13 +73,13 @@ class RecursivePictureMenu : DialogFragment() {
val title: Int
@DrawableRes
val mIcon: Int
private val mAnalyticsId: String?
val icon: Int
private val analyticsId: String?
constructor(@StringRes titleString: Int, @DrawableRes iconDrawable: Int, analyticsId: String?) {
title = titleString
mIcon = iconDrawable
mAnalyticsId = analyticsId
icon = iconDrawable
this.analyticsId = analyticsId
}
open val children: List<Item?>
@ -87,8 +87,8 @@ class RecursivePictureMenu : DialogFragment() {
protected constructor(parcel: Parcel) {
title = parcel.readInt()
mIcon = parcel.readInt()
mAnalyticsId = parcel.readString()
icon = parcel.readInt()
analyticsId = parcel.readString()
}
override fun describeContents(): Int {
@ -97,13 +97,13 @@ class RecursivePictureMenu : DialogFragment() {
override fun writeToParcel(dest: Parcel, flags: Int) {
dest.writeInt(title)
dest.writeInt(mIcon)
dest.writeString(mAnalyticsId)
dest.writeInt(icon)
dest.writeString(analyticsId)
}
protected abstract fun onClicked(activity: AnkiActivity)
fun sendAnalytics() {
UsageAnalytics.sendAnalyticsEvent(UsageAnalytics.Category.LINK_CLICKED, mAnalyticsId!!)
UsageAnalytics.sendAnalyticsEvent(UsageAnalytics.Category.LINK_CLICKED, analyticsId!!)
}
/* This method calls onClicked method to handle click event in a suitable manner and
@ -118,14 +118,14 @@ class RecursivePictureMenu : DialogFragment() {
}
class ItemHeader : Item, Parcelable {
private val mChildren: MutableList<Item?>?
private val _children: MutableList<Item?>?
constructor(@StringRes titleString: Int, i: Int, analyticsStringId: String?, vararg children: Item?) : super(titleString, i, analyticsStringId) {
mChildren = ArrayList(listOf(*children))
_children = ArrayList(listOf(*children))
}
override val children: List<Item?>
get() = ArrayList(mChildren!!.toMutableList())
get() = ArrayList(_children!!.toMutableList())
public override fun onClicked(activity: AnkiActivity) {
val children = ArrayList(children)
@ -134,28 +134,28 @@ class RecursivePictureMenu : DialogFragment() {
}
override fun remove(toRemove: Item?) {
mChildren!!.remove(toRemove)
for (i in mChildren) {
_children!!.remove(toRemove)
for (i in _children) {
i!!.remove(toRemove)
}
}
protected constructor(parcel: Parcel) : super(parcel) {
if (parcel.readByte().toInt() == 0x01) {
mChildren = ArrayList()
ParcelCompat.readList(parcel, mChildren, Item::class.java.classLoader, Item::class.java)
_children = ArrayList()
ParcelCompat.readList(parcel, _children, Item::class.java.classLoader, Item::class.java)
} else {
mChildren = ArrayList(0)
_children = ArrayList(0)
}
}
override fun writeToParcel(dest: Parcel, flags: Int) {
super.writeToParcel(dest, flags)
if (mChildren == null) {
if (_children == null) {
dest.writeByte(0x00.toByte())
} else {
dest.writeByte(0x01.toByte())
dest.writeList(mChildren)
dest.writeList(_children)
}
}

View File

@ -46,13 +46,13 @@ import java.util.function.Supplier
* A delegate class used in any [AnkiActivity] where the exporting feature is required.
*
* Must be constructed before calling [AnkiActivity.onCreate(Bundle, PersistableBundle)][AnkiActivity.onCreate],
* to ensure the fragment factory ([mDialogsFactory]) is set correctly.
* to ensure the fragment factory ([dialogsFactory]) is set correctly.
*
* @param activity the calling activity (must implement [ExportReadyDialogListener])
* @param collectionSupplier a predicate that supplies a collection instance
*/
class ActivityExportingDelegate(private val activity: AnkiActivity, private val collectionSupplier: Supplier<Collection>) : ExportReadyDialogListener {
val mDialogsFactory: ExportDialogsFactory
val dialogsFactory: ExportDialogsFactory
private val saveFileLauncher: ActivityResultLauncher<Intent>
private lateinit var fileExportPath: String
@ -186,8 +186,8 @@ class ActivityExportingDelegate(private val activity: AnkiActivity, private val
init {
val fragmentManager = activity.supportFragmentManager
mDialogsFactory = ExportDialogsFactory(this).attachToActivity(activity)
fragmentManager.fragmentFactory = mDialogsFactory
dialogsFactory = ExportDialogsFactory(this).attachToActivity(activity)
fragmentManager.fragmentFactory = dialogsFactory
saveFileLauncher = activity.registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { result: ActivityResult ->

View File

@ -28,8 +28,8 @@ import timber.log.Timber
import java.io.IOException
class AudioRecorder {
private lateinit var mRecorder: MediaRecorder
private var mOnRecordingInitialized: Runnable? = null
private lateinit var recorder: MediaRecorder
private var onRecordingInitialized: Runnable? = null
private var previousNonZeroAmplitude = 0
private fun initMediaRecorder(context: Context, audioPath: String): MediaRecorder {
val mr = CompatHelper.compat.getMediaRecorder(context)
@ -41,7 +41,7 @@ class AudioRecorder {
}
private fun onRecordingInitialized() {
mOnRecordingInitialized?.run()
onRecordingInitialized?.run()
}
@Throws(IOException::class)
@ -50,14 +50,14 @@ class AudioRecorder {
try {
// try high quality AAC @ 44.1kHz / 192kbps first
// can throw IllegalArgumentException if codec isn't supported
mRecorder = initMediaRecorder(context, audioPath)
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC)
mRecorder.setAudioChannels(2)
mRecorder.setAudioSamplingRate(44100)
mRecorder.setAudioEncodingBitRate(192000)
recorder = initMediaRecorder(context, audioPath)
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC)
recorder.setAudioChannels(2)
recorder.setAudioSamplingRate(44100)
recorder.setAudioEncodingBitRate(192000)
// this can also throw IOException if output path is invalid
mRecorder.prepare()
mRecorder.start()
recorder.prepare()
recorder.start()
highSampling = true
} catch (e: Exception) {
Timber.w(e)
@ -66,32 +66,32 @@ class AudioRecorder {
if (!highSampling) {
// if we are here, either the codec didn't work or output file was invalid
// fall back on default
mRecorder = initMediaRecorder(context, audioPath)
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB)
mRecorder.prepare()
mRecorder.start()
recorder = initMediaRecorder(context, audioPath)
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB)
recorder.prepare()
recorder.start()
}
}
fun stopRecording() {
if (this::mRecorder.isInitialized) {
mRecorder.stop()
if (this::recorder.isInitialized) {
recorder.stop()
}
}
fun setOnRecordingInitializedHandler(onRecordingInitialized: Runnable?) {
mOnRecordingInitialized = onRecordingInitialized
this.onRecordingInitialized = onRecordingInitialized
}
fun release() {
if (this::mRecorder.isInitialized) {
mRecorder.release()
if (this::recorder.isInitialized) {
recorder.release()
}
}
fun maxAmplitude(): Int {
val currentAmplitude = if (this::mRecorder.isInitialized) {
mRecorder.maxAmplitude
val currentAmplitude = if (this::recorder.isInitialized) {
recorder.maxAmplitude
} else {
0
}
@ -104,22 +104,22 @@ class AudioRecorder {
}
fun pause() {
if (!this::mRecorder.isInitialized) {
if (!this::recorder.isInitialized) {
return
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
mRecorder.pause()
recorder.pause()
} else {
mRecorder.stop()
recorder.stop()
}
}
fun resume() {
if (this::mRecorder.isInitialized) {
if (this::recorder.isInitialized) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
mRecorder.resume()
recorder.resume()
} else {
mRecorder.start()
recorder.start()
}
}
}

View File

@ -45,9 +45,9 @@ import java.text.DecimalFormat
@KotlinCleanup("lateinit")
class MultimediaEditFieldActivity : AnkiActivity(), OnRequestPermissionsResultCallback {
private lateinit var mField: IField
private lateinit var mNote: IMultimediaEditableNote
private var mFieldIndex = 0
private lateinit var field: IField
private lateinit var note: IMultimediaEditableNote
private var fieldIndex = 0
@get:VisibleForTesting
var fieldController: IFieldController? = null
@ -57,7 +57,7 @@ class MultimediaEditFieldActivity : AnkiActivity(), OnRequestPermissionsResultCa
* Cached copy of the current request to change a field
* Used to access past state from OnRequestPermissionsResultCallback
*/
private var mCurrentChangeRequest: ChangeUIRequest? = null
private var currentChangeRequest: ChangeUIRequest? = null
override fun onCreate(savedInstanceState: Bundle?) {
if (showedActivityFailedScreen(savedInstanceState)) {
return
@ -85,11 +85,11 @@ class MultimediaEditFieldActivity : AnkiActivity(), OnRequestPermissionsResultCa
finishCancel()
return
}
mFieldIndex = extras.first
mField = extras.second
mNote = extras.third
fieldIndex = extras.first
field = extras.second
note = extras.third
onBack()
recreateEditingUi(ChangeUIRequest.init(mField), controllerBundle)
recreateEditingUi(ChangeUIRequest.init(field), controllerBundle)
}
// in case media is saved by view button then allows it to be inserted into the filed
@ -122,9 +122,9 @@ class MultimediaEditFieldActivity : AnkiActivity(), OnRequestPermissionsResultCa
private fun setupUIController(fieldController: IFieldController, savedInstanceState: Bundle?) {
fieldController.apply {
setField(mField)
setFieldIndex(mFieldIndex)
setNote(mNote)
setField(field)
setFieldIndex(fieldIndex)
setNote(note)
setEditingActivity(this@MultimediaEditFieldActivity)
loadInstanceState(savedInstanceState)
}
@ -134,7 +134,7 @@ class MultimediaEditFieldActivity : AnkiActivity(), OnRequestPermissionsResultCa
Timber.d("recreateEditingUi()")
// Permissions are checked async, save our current state to allow continuation
mCurrentChangeRequest = newUI
currentChangeRequest = newUI
// If we went through the permission check once, we don't need to do it again.
// As we only get here a second time if we have the required permissions
@ -145,7 +145,7 @@ class MultimediaEditFieldActivity : AnkiActivity(), OnRequestPermissionsResultCa
val fieldController = createControllerForField(newUI.field)
UIRecreationHandler.onPreFieldControllerReplacement(this.fieldController)
this.fieldController = fieldController
mField = newUI.field
field = newUI.field
setupUIController(this.fieldController!!, savedInstanceState)
val linearLayout = findViewById<LinearLayout>(R.id.LinearLayoutInScrollViewFieldEdit)
linearLayout.removeAllViews()
@ -154,13 +154,13 @@ class MultimediaEditFieldActivity : AnkiActivity(), OnRequestPermissionsResultCa
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
Timber.d("onCreateOptionsMenu() - mField.getType() = %s", mField.type)
Timber.d("onCreateOptionsMenu() - mField.getType() = %s", field.type)
// Inflate the menu; this adds items to the action bar if it is present.
menuInflater.inflate(R.menu.activity_edit_text, menu)
menu.findItem(R.id.multimedia_edit_field_to_text).isVisible = mField.type !== EFieldType.TEXT
menu.findItem(R.id.multimedia_edit_field_to_audio).isVisible = mField.type !== EFieldType.AUDIO_RECORDING
menu.findItem(R.id.multimedia_edit_field_to_audio_clip).isVisible = mField.type !== EFieldType.MEDIA_CLIP
menu.findItem(R.id.multimedia_edit_field_to_image).isVisible = mField.type !== EFieldType.IMAGE
menu.findItem(R.id.multimedia_edit_field_to_text).isVisible = field.type !== EFieldType.TEXT
menu.findItem(R.id.multimedia_edit_field_to_audio).isVisible = field.type !== EFieldType.AUDIO_RECORDING
menu.findItem(R.id.multimedia_edit_field_to_audio_clip).isVisible = field.type !== EFieldType.MEDIA_CLIP
menu.findItem(R.id.multimedia_edit_field_to_image).isVisible = field.type !== EFieldType.IMAGE
return true
}
@ -198,12 +198,12 @@ class MultimediaEditFieldActivity : AnkiActivity(), OnRequestPermissionsResultCa
@KotlinCleanup("rename: bChangeToText")
private fun done() {
var bChangeToText = false
if (mField.type === EFieldType.IMAGE) {
if (mField.imagePath == null) {
if (field.type === EFieldType.IMAGE) {
if (field.imagePath == null) {
bChangeToText = true
}
if (!bChangeToText) {
val f = File(mField.imagePath!!)
val f = File(field.imagePath!!)
if (!f.exists()) {
bChangeToText = true
} else {
@ -214,12 +214,12 @@ class MultimediaEditFieldActivity : AnkiActivity(), OnRequestPermissionsResultCa
}
}
}
} else if (mField.type === EFieldType.AUDIO_RECORDING) {
if (mField.audioPath == null) {
} else if (field.type === EFieldType.AUDIO_RECORDING) {
if (field.audioPath == null) {
bChangeToText = true
}
if (!bChangeToText) {
val f = File(mField.audioPath!!)
val f = File(field.audioPath!!)
if (!f.exists()) {
bChangeToText = true
}
@ -230,28 +230,28 @@ class MultimediaEditFieldActivity : AnkiActivity(), OnRequestPermissionsResultCa
}
private fun toAudioRecordingField() {
if (mField.type !== EFieldType.AUDIO_RECORDING) {
if (field.type !== EFieldType.AUDIO_RECORDING) {
val request = ChangeUIRequest.uiChange(AudioRecordingField())
recreateEditingUi(request)
}
}
private fun toAudioClipField() {
if (mField.type !== EFieldType.MEDIA_CLIP) {
if (field.type !== EFieldType.MEDIA_CLIP) {
val request = ChangeUIRequest.uiChange(MediaClipField())
recreateEditingUi(request)
}
}
private fun toImageField() {
if (mField.type !== EFieldType.IMAGE) {
if (field.type !== EFieldType.IMAGE) {
val request = ChangeUIRequest.uiChange(ImageField())
recreateEditingUi(request)
}
}
private fun toTextField() {
if (mField.type !== EFieldType.TEXT) {
if (field.type !== EFieldType.TEXT) {
val request = ChangeUIRequest.uiChange(TextField())
recreateEditingUi(request)
}
@ -259,15 +259,15 @@ class MultimediaEditFieldActivity : AnkiActivity(), OnRequestPermissionsResultCa
private fun recreateEditingUIUsingCachedRequest() {
Timber.d("recreateEditingUIUsingCachedRequest()")
if (mCurrentChangeRequest == null) {
if (currentChangeRequest == null) {
cancelActivityWithAssertionFailure("mCurrentChangeRequest should be set before using cached request")
return
}
recreateEditingUi(mCurrentChangeRequest!!)
recreateEditingUi(currentChangeRequest!!)
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
if (mCurrentChangeRequest == null) {
if (currentChangeRequest == null) {
cancelActivityWithAssertionFailure("mCurrentChangeRequest should be set before requesting permissions")
return
}
@ -283,7 +283,7 @@ class MultimediaEditFieldActivity : AnkiActivity(), OnRequestPermissionsResultCa
resources.getString(R.string.multimedia_editor_audio_permission_refused),
true
)
UIRecreationHandler.onRequiredPermissionDenied(mCurrentChangeRequest!!, this)
UIRecreationHandler.onRequiredPermissionDenied(currentChangeRequest!!, this)
}
if (requestCode == REQUEST_CAMERA_PERMISSION && permissions.size == 1) {
if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
@ -319,8 +319,8 @@ class MultimediaEditFieldActivity : AnkiActivity(), OnRequestPermissionsResultCa
private fun saveAndExit(ignoreField: Boolean = false) {
val resultData = Intent().apply {
putExtra(EXTRA_RESULT_FIELD, if (ignoreField) null else mField)
putExtra(EXTRA_RESULT_FIELD_INDEX, mFieldIndex)
putExtra(EXTRA_RESULT_FIELD, if (ignoreField) null else field)
putExtra(EXTRA_RESULT_FIELD_INDEX, fieldIndex)
}
setResult(RESULT_OK, resultData)
finish()

View File

@ -20,21 +20,23 @@
package com.ichi2.anki.multimediacard.fields
import com.ichi2.libanki.Collection
import com.ichi2.utils.KotlinCleanup
import java.io.File
import java.util.regex.Pattern
/**
* Implementation of Audio field types
*/
@KotlinCleanup("replace _audioPath with `field`")
abstract class AudioField : FieldBase(), IField {
private var mAudioPath: String? = null
private var _audioPath: String? = null
override var imagePath: String? = null
override var audioPath: String?
get() = mAudioPath
get() = _audioPath
set(value) {
mAudioPath = value
_audioPath = value
setThisModified()
}

View File

@ -74,16 +74,16 @@ import kotlin.math.roundToLong
class BasicImageFieldController : FieldControllerBase(), IFieldController {
@KotlinCleanup("lateinit wherever possible")
private lateinit var mImagePreview: ImageView
private lateinit var mImageFileSize: TextView
private lateinit var mImageFileSizeWarning: TextView
private var mViewModel = ImageViewModel(null, null)
private var mPreviousImagePath: String? = null // save the latest path to prevent from cropping or taking photo action canceled
private var mPreviousImageUri: Uri? = null
private var mAnkiCacheDirectory: String? = null // system provided 'External Cache Dir' with "temp-photos" on it
private lateinit var imagePreview: ImageView
private lateinit var imageFileSize: TextView
private lateinit var imageFileSizeWarning: TextView
private var viewModel = ImageViewModel(null, null)
private var previousImagePath: String? = null // save the latest path to prevent from cropping or taking photo action canceled
private var previousImageUri: Uri? = null
private var ankiCacheDirectory: String? = null // system provided 'External Cache Dir' with "temp-photos" on it
// e.g. '/self/primary/Android/data/com.ichi2.anki.AnkiDroid/cache/temp-photos'
private lateinit var mCropButton: Button
private lateinit var cropButton: Button
private val maxImageSize: Int
get() {
val metrics = displayMetrics
@ -117,14 +117,14 @@ class BasicImageFieldController : FieldControllerBase(), IFieldController {
// Some apps send this back with app-specific data, direct the user to another app
if (result.resultCode >= Activity.RESULT_FIRST_USER) {
UIUtils.showThemedToast(mActivity, mActivity.getString(R.string.activity_result_unexpected), true)
UIUtils.showThemedToast(_activity, _activity.getString(R.string.activity_result_unexpected), true)
}
return
}
mImageFileSizeWarning.visibility = View.GONE
imageFileSizeWarning.visibility = View.GONE
onSuccess(result)
setPreviewImage(mViewModel.imagePath, maxImageSize)
setPreviewImage(viewModel.imagePath, maxImageSize)
}
}
@ -135,25 +135,25 @@ class BasicImageFieldController : FieldControllerBase(), IFieldController {
}
Timber.i("loadInstanceState loading saved state...")
mViewModel = ImageViewModel.fromBundle(savedInstanceState)
mPreviousImagePath = savedInstanceState.getString("mPreviousImagePath")
mPreviousImageUri = BundleCompat.getParcelable(savedInstanceState, "mPreviousImageUri", Uri::class.java)
viewModel = ImageViewModel.fromBundle(savedInstanceState)
previousImagePath = savedInstanceState.getString("mPreviousImagePath")
previousImageUri = BundleCompat.getParcelable(savedInstanceState, "mPreviousImageUri", Uri::class.java)
}
override fun saveInstanceState(): Bundle {
Timber.d("saveInstanceState")
val savedInstanceState = Bundle()
mViewModel.enrich(savedInstanceState)
savedInstanceState.putString("mPreviousImagePath", mPreviousImagePath)
savedInstanceState.putParcelable("mPreviousImageUri", mPreviousImageUri)
viewModel.enrich(savedInstanceState)
savedInstanceState.putString("mPreviousImagePath", previousImagePath)
savedInstanceState.putParcelable("mPreviousImageUri", previousImageUri)
return savedInstanceState
}
override fun createUI(context: Context, layout: LinearLayout) {
Timber.d("createUI()")
mViewModel = mViewModel.replaceNullValues(mField, mActivity)
viewModel = viewModel.replaceNullValues(_field, _activity)
mImagePreview = ImageView(mActivity)
imagePreview = ImageView(_activity)
val externalCacheDirRoot = context.externalCacheDir
if (externalCacheDirRoot == null) {
Timber.e("createUI() unable to get external cache directory")
@ -166,7 +166,7 @@ class BasicImageFieldController : FieldControllerBase(), IFieldController {
showSomethingWentWrong()
return
}
mAnkiCacheDirectory = externalCacheDir.absolutePath
ankiCacheDirectory = externalCacheDir.absolutePath
val p = LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
@ -175,13 +175,13 @@ class BasicImageFieldController : FieldControllerBase(), IFieldController {
drawUIComponents(context)
mCropButton = Button(mActivity).apply {
cropButton = Button(_activity).apply {
text = gtxt(R.string.crop_button)
setOnClickListener { mViewModel = requestCrop(mViewModel) }
setOnClickListener { viewModel = requestCrop(viewModel) }
visibility = View.INVISIBLE
}
val btnGallery = Button(mActivity).apply {
val btnGallery = Button(_activity).apply {
text = gtxt(R.string.multimedia_editor_image_field_editing_galery)
setOnClickListener {
val i = Intent(Intent.ACTION_PICK)
@ -190,26 +190,26 @@ class BasicImageFieldController : FieldControllerBase(), IFieldController {
}
}
val btnDraw = Button(mActivity).apply {
val btnDraw = Button(_activity).apply {
text = gtxt(R.string.drawing)
setOnClickListener {
drawingLauncher.launch(Intent(mActivity, DrawingActivity::class.java))
drawingLauncher.launch(Intent(_activity, DrawingActivity::class.java))
}
}
val btnCamera = Button(mActivity).apply {
val btnCamera = Button(_activity).apply {
text = gtxt(R.string.multimedia_editor_image_field_editing_photo)
setOnClickListener { mViewModel = captureImage(context) }
setOnClickListener { viewModel = captureImage(context) }
if (!canUseCamera(context)) {
visibility = View.INVISIBLE
}
}
setPreviewImage(mViewModel.imagePath, maxImageSize)
setPreviewImage(viewModel.imagePath, maxImageSize)
layout.addView(mImagePreview, ViewGroup.LayoutParams.MATCH_PARENT, p)
layout.addView(mImageFileSize, ViewGroup.LayoutParams.MATCH_PARENT)
layout.addView(mImageFileSizeWarning, ViewGroup.LayoutParams.MATCH_PARENT)
layout.addView(imagePreview, ViewGroup.LayoutParams.MATCH_PARENT, p)
layout.addView(imageFileSize, ViewGroup.LayoutParams.MATCH_PARENT)
layout.addView(imageFileSizeWarning, ViewGroup.LayoutParams.MATCH_PARENT)
layout.addView(btnGallery, ViewGroup.LayoutParams.MATCH_PARENT)
// drew image appear far larger in preview in devices API < 24 #9439
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
@ -218,22 +218,22 @@ class BasicImageFieldController : FieldControllerBase(), IFieldController {
if (canUseCamera(context)) {
layout.addView(btnCamera, ViewGroup.LayoutParams.MATCH_PARENT)
}
layout.addView(mCropButton, ViewGroup.LayoutParams.MATCH_PARENT)
layout.addView(cropButton, ViewGroup.LayoutParams.MATCH_PARENT)
}
override fun setEditingActivity(activity: MultimediaEditFieldActivity) {
super.setEditingActivity(activity)
val registryToUse = if (this::registryToUse.isInitialized) registryToUse else mActivity.activityResultRegistry
val registryToUse = if (this::registryToUse.isInitialized) registryToUse else this._activity.activityResultRegistry
@NeedsTest("check the happy/failure path for the crop action")
cropImageRequest = registryToUse.register(CROP_IMAGE_LAUNCHER_KEY, CropImageContract()) { cropResult ->
if (cropResult.isSuccessful) {
mImageFileSizeWarning.visibility = View.GONE
imageFileSizeWarning.visibility = View.GONE
if (cropResult != null) {
handleCropResult(cropResult)
}
setPreviewImage(mViewModel.imagePath, maxImageSize)
setPreviewImage(viewModel.imagePath, maxImageSize)
} else {
if (!mPreviousImagePath.isNullOrEmpty()) {
if (!previousImagePath.isNullOrEmpty()) {
revertToPreviousImage()
}
// cropImage can give us more information. Not sure it is actionable so for now just log it.
@ -268,7 +268,7 @@ class BasicImageFieldController : FieldControllerBase(), IFieldController {
onSuccess = {
try {
handleSelectImageIntent(it.data)
mImageFileSizeWarning.visibility = View.GONE
imageFileSizeWarning.visibility = View.GONE
} catch (e: Exception) {
CrashReportService.sendExceptionReport(e, "BasicImageFieldController - handleSelectImageIntent")
Timber.e(e, "Failed to select image")
@ -315,7 +315,7 @@ class BasicImageFieldController : FieldControllerBase(), IFieldController {
private fun captureImage(context: Context): ImageViewModel {
val cameraIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
val image: File
var toReturn = mViewModel
var toReturn = viewModel
try {
saveImageForRevert()
@ -339,28 +339,28 @@ class BasicImageFieldController : FieldControllerBase(), IFieldController {
}
private fun saveImageForRevert() {
if (!mViewModel.isPreExistingImage) {
if (!viewModel.isPreExistingImage) {
deletePreviousImage()
}
mPreviousImagePath = mViewModel.imagePath
mPreviousImageUri = mViewModel.imageUri
previousImagePath = viewModel.imagePath
previousImageUri = viewModel.imageUri
}
private fun deletePreviousImage() {
// Store the old image path for deletion / error handling if the user cancels
if (mPreviousImagePath != null && !File(mPreviousImagePath!!).delete()) {
if (previousImagePath != null && !File(previousImagePath!!).delete()) {
Timber.i("deletePreviousImage() unable to delete previous image file")
}
}
@Throws(IOException::class)
private fun createNewCacheImageFile(extension: String = "jpg"): File {
val storageDir = File(mAnkiCacheDirectory!!)
val storageDir = File(ankiCacheDirectory!!)
return File.createTempFile("img", ".$extension", storageDir)
}
@Throws(IOException::class)
private fun createCachedFile(filename: String) = File(mAnkiCacheDirectory, filename).apply {
private fun createCachedFile(filename: String) = File(ankiCacheDirectory, filename).apply {
deleteOnExit()
}
@ -370,7 +370,7 @@ class BasicImageFieldController : FieldControllerBase(), IFieldController {
val height = metrics.heightPixels
val width = metrics.widthPixels
mImagePreview = ImageView(mActivity).apply {
imagePreview = ImageView(_activity).apply {
scaleType = ImageView.ScaleType.CENTER_INSIDE
adjustViewBounds = true
@ -378,7 +378,7 @@ class BasicImageFieldController : FieldControllerBase(), IFieldController {
maxWidth = (width * 0.6).roundToLong().toInt()
}
mImageFileSize = FixedEditText(context).apply {
imageFileSize = FixedEditText(context).apply {
maxWidth = (width * 0.6).roundToLong().toInt()
isEnabled = false
gravity = Gravity.CENTER_HORIZONTAL
@ -388,7 +388,7 @@ class BasicImageFieldController : FieldControllerBase(), IFieldController {
// #5513 - Image compression failed, but we'll confuse most users if we tell them that. Instead, just imply that
// there's an action that they can take.
mImageFileSizeWarning = FixedEditText(context).apply {
imageFileSizeWarning = FixedEditText(context).apply {
maxWidth = (width * 0.6).roundToLong().toInt()
isEnabled = false
setTextColor(Color.parseColor("#FF4500")) // Orange-Red
@ -399,34 +399,34 @@ class BasicImageFieldController : FieldControllerBase(), IFieldController {
}
private fun gtxt(id: Int): String {
return mActivity.getText(id).toString()
return _activity.getText(id).toString()
}
// #9333: getDefaultDisplay & getMetrics
@Suppress("deprecation") // defaultDisplay
private val displayMetrics: DisplayMetrics by lazy {
DisplayMetrics().apply {
mActivity.windowManager.defaultDisplay.getMetrics(this)
_activity.windowManager.defaultDisplay.getMetrics(this)
}
}
private fun cancelImageCapture() {
if (!mPreviousImagePath.isNullOrEmpty()) {
if (!previousImagePath.isNullOrEmpty()) {
revertToPreviousImage()
}
}
private fun revertToPreviousImage() {
mViewModel.deleteImagePath()
mViewModel = ImageViewModel(mPreviousImagePath, mPreviousImageUri)
mField.imagePath = mPreviousImagePath
mPreviousImagePath = null
mPreviousImageUri = null
viewModel.deleteImagePath()
viewModel = ImageViewModel(previousImagePath, previousImageUri)
_field.imagePath = previousImagePath
previousImagePath = null
previousImageUri = null
}
private fun showSomethingWentWrong() {
try {
UIUtils.showThemedToast(mActivity, mActivity.resources.getString(R.string.multimedia_editor_something_wrong), false)
UIUtils.showThemedToast(_activity, _activity.resources.getString(R.string.multimedia_editor_something_wrong), false)
} catch (e: Exception) {
// ignore. A NullPointerException may occur in Robolectric
Timber.w(e, "Failed to display toast")
@ -434,7 +434,7 @@ class BasicImageFieldController : FieldControllerBase(), IFieldController {
}
private fun showSVGPreviewToast() {
UIUtils.showThemedToast(mActivity, mActivity.resources.getString(R.string.multimedia_editor_svg_preview), false)
UIUtils.showThemedToast(_activity, _activity.resources.getString(R.string.multimedia_editor_svg_preview), false)
}
private fun handleSelectImageIntent(data: Intent?) {
@ -450,7 +450,7 @@ class BasicImageFieldController : FieldControllerBase(), IFieldController {
if (data.extras == null) "null" else data.extras!!.keySet().joinToString(", ")
)
val selectedImage = getImageUri(mActivity, data)
val selectedImage = getImageUri(_activity, data)
if (selectedImage == null) {
Timber.w("handleSelectImageIntent() selectedImage was null")
showSomethingWentWrong()
@ -465,7 +465,7 @@ class BasicImageFieldController : FieldControllerBase(), IFieldController {
}
val imagePath = internalizedPick.absolutePath
mViewModel = ImageViewModel(imagePath, getUriForFile(internalizedPick))
viewModel = ImageViewModel(imagePath, getUriForFile(internalizedPick))
setTemporaryMedia(imagePath)
Timber.i("handleSelectImageIntent() Decoded image: '%s'", imagePath)
@ -486,7 +486,7 @@ class BasicImageFieldController : FieldControllerBase(), IFieldController {
}
val drewImagePath = internalizedPick.absolutePath
mViewModel = ImageViewModel(drewImagePath, imageUri)
viewModel = ImageViewModel(drewImagePath, imageUri)
setTemporaryMedia(drewImagePath)
Timber.i("handleDrawingResult() Decoded image: '%s'", drewImagePath)
@ -494,7 +494,7 @@ class BasicImageFieldController : FieldControllerBase(), IFieldController {
private fun internalizeUri(uri: Uri): File? {
val internalFile: File
val uriFileName = getImageNameFromUri(mActivity, uri)
val uriFileName = getImageNameFromUri(_activity, uri)
// Use the display name from the image info to create a new file with correct extension
if (uriFileName == null) {
@ -510,7 +510,7 @@ class BasicImageFieldController : FieldControllerBase(), IFieldController {
return null
}
return try {
val returnFile = FileUtil.internalizeUri(uri, internalFile, mActivity.contentResolver)
val returnFile = FileUtil.internalizeUri(uri, internalFile, _activity.contentResolver)
Timber.d("internalizeUri successful. Returning internalFile.")
returnFile
} catch (e: Exception) {
@ -569,8 +569,8 @@ class BasicImageFieldController : FieldControllerBase(), IFieldController {
if (!f.delete()) {
Timber.w("rotateAndCompress() delete of pre-compressed image failed %s", imagePath)
}
mViewModel = imageViewModel.rotateAndCompressTo(outFile.absolutePath, getUriForFile(outFile))
mField.imagePath = outFile.absolutePath
viewModel = imageViewModel.rotateAndCompressTo(outFile.absolutePath, getUriForFile(outFile))
_field.imagePath = outFile.absolutePath
Timber.d("rotateAndCompress out path %s has size %d", outFile.absolutePath, outFile.length())
} catch (e: FileNotFoundException) {
Timber.w(e, "rotateAndCompress() File not found for image compression %s", imagePath)
@ -607,22 +607,22 @@ class BasicImageFieldController : FieldControllerBase(), IFieldController {
}
Timber.d("setPreviewImage path %s has size %d", f.absolutePath, f.length())
b = ExifUtil.rotateFromCamera(f, b)
onValidImage(b, Formatter.formatFileSize(mActivity, f.length()))
onValidImage(b, Formatter.formatFileSize(_activity, f.length()))
}
}
private fun onValidImage(b: Bitmap, fileSize: String) {
mImagePreview.setImageBitmap(b)
mImageFileSize.visibility = View.VISIBLE
mImageFileSize.text = fileSize
mCropButton.visibility = View.VISIBLE
imagePreview.setImageBitmap(b)
imageFileSize.visibility = View.VISIBLE
imageFileSize.text = fileSize
cropButton.visibility = View.VISIBLE
}
// ensure the previous preview is not visible
private fun hideImagePreview() {
BitmapUtil.freeImageView(mImagePreview)
if (::mCropButton.isInitialized) mCropButton.visibility = View.INVISIBLE
if (::mImageFileSize.isInitialized) mImageFileSize.visibility = View.INVISIBLE
BitmapUtil.freeImageView(imagePreview)
if (::cropButton.isInitialized) cropButton.visibility = View.INVISIBLE
if (::imageFileSize.isInitialized) imageFileSize.visibility = View.INVISIBLE
}
override fun onDestroy() {
@ -635,7 +635,7 @@ class BasicImageFieldController : FieldControllerBase(), IFieldController {
Timber.i("handleTakePictureResult appears to have an invalid picture")
return
}
showCropDialog(mActivity.getString(R.string.crop_image), null)
showCropDialog(_activity.getString(R.string.crop_image), null)
}
/**
@ -677,22 +677,22 @@ class BasicImageFieldController : FieldControllerBase(), IFieldController {
}
private fun setTemporaryMedia(imagePath: String) {
mField.apply {
_field.apply {
this.imagePath = imagePath
hasTemporaryMedia = true
}
}
fun showCropDialog(content: String, negativeCallback: (() -> Unit)?) {
if (!mViewModel.isValid) {
if (!viewModel.isValid) {
Timber.w("showCropDialog called with null URI or Path")
return
}
AlertDialog.Builder(mActivity).show {
AlertDialog.Builder(_activity).show {
message(text = content)
positiveButton(R.string.dialog_yes) {
mViewModel = requestCrop(mViewModel)
viewModel = requestCrop(viewModel)
}
negativeButton(R.string.dialog_no) {
negativeCallback?.invoke() // Using invoke since negativeCallback is nullable
@ -702,28 +702,28 @@ class BasicImageFieldController : FieldControllerBase(), IFieldController {
private fun handleCropResult(result: CropImageView.CropResult) {
Timber.d("handleCropResult")
mViewModel.deleteImagePath()
mViewModel = ImageViewModel(result.getUriFilePath(mActivity, true), result.uriContent)
viewModel.deleteImagePath()
viewModel = ImageViewModel(result.getUriFilePath(_activity, true), result.uriContent)
if (!rotateAndCompress()) {
Timber.i("handleCropResult() appears to have an invalid file, reverting")
return
}
Timber.d("handleCropResult() = image path now %s", mField.imagePath)
Timber.d("handleCropResult() = image path now %s", _field.imagePath)
}
private fun rotateAndCompress(): Boolean {
if (!rotateAndCompress(mViewModel.imagePath!!, mViewModel)) {
mImageFileSizeWarning.visibility = View.VISIBLE
if (!rotateAndCompress(viewModel.imagePath!!, viewModel)) {
imageFileSizeWarning.visibility = View.VISIBLE
revertToPreviousImage()
showSomethingWentWrong()
return false
}
mField.hasTemporaryMedia = true
_field.hasTemporaryMedia = true
return true
}
private fun getUriForFile(file: File): Uri {
return getUriForFile(file, mActivity)
return getUriForFile(file, _activity)
}
/**
@ -800,7 +800,7 @@ class BasicImageFieldController : FieldControllerBase(), IFieldController {
}
val isShowingPreview: Boolean
get() = mImageFileSize.visibility == View.VISIBLE
get() = imageFileSize.visibility == View.VISIBLE
private class ImageViewModel(val imagePath: String?, val imageUri: Uri?) {
var isPreExistingImage = false

View File

@ -50,8 +50,8 @@ class BasicMediaClipFieldController : FieldControllerBase(), IFieldController {
ankiCacheDirectory = context.externalCacheDir?.absolutePath
// #9639: .opus is application/octet-stream in API 26,
// requires a workaround as we don't want to enable application/octet-stream by default
val btnLibrary = Button(mActivity)
btnLibrary.text = mActivity.getText(R.string.multimedia_editor_import_audio)
val btnLibrary = Button(_activity)
btnLibrary.text = _activity.getText(R.string.multimedia_editor_import_audio)
btnLibrary.setOnClickListener {
openChooserPrompt(
"audio/*",
@ -60,8 +60,8 @@ class BasicMediaClipFieldController : FieldControllerBase(), IFieldController {
)
}
layout.addView(btnLibrary, ViewGroup.LayoutParams.MATCH_PARENT)
val btnVideo = Button(mActivity).apply {
text = mActivity.getText(R.string.multimedia_editor_import_video)
val btnVideo = Button(_activity).apply {
text = _activity.getText(R.string.multimedia_editor_import_video)
setOnClickListener {
openChooserPrompt(
"video/*",
@ -71,11 +71,11 @@ class BasicMediaClipFieldController : FieldControllerBase(), IFieldController {
}
}
layout.addView(btnVideo, ViewGroup.LayoutParams.MATCH_PARENT)
tvAudioClip = FixedTextView(mActivity)
if (mField.audioPath == null) {
tvAudioClip = FixedTextView(_activity)
if (_field.audioPath == null) {
tvAudioClip.visibility = View.GONE
} else {
tvAudioClip.text = mField.audioPath
tvAudioClip.text = _field.audioPath
tvAudioClip.visibility = View.VISIBLE
}
layout.addView(tvAudioClip, ViewGroup.LayoutParams.MATCH_PARENT)
@ -83,7 +83,7 @@ class BasicMediaClipFieldController : FieldControllerBase(), IFieldController {
private fun openChooserPrompt(initialMimeType: String, extraMimeTypes: Array<String>, @StringRes prompt: Int) {
val allowAllFiles =
this.mActivity.sharedPrefs().getBoolean("mediaImportAllowAllFiles", false)
this._activity.sharedPrefs().getBoolean("mediaImportAllowAllFiles", false)
val i = Intent()
i.type = if (allowAllFiles) "*/*" else initialMimeType
if (!allowAllFiles && extraMimeTypes.any()) {
@ -94,17 +94,17 @@ class BasicMediaClipFieldController : FieldControllerBase(), IFieldController {
i.action = Intent.ACTION_GET_CONTENT
// Only get openable files, to avoid virtual files issues with Android 7+
i.addCategory(Intent.CATEGORY_OPENABLE)
val chooserPrompt = mActivity.resources.getString(prompt)
val chooserPrompt = _activity.resources.getString(prompt)
selectMediaLauncher.launch(Intent.createChooser(i, chooserPrompt))
}
override fun setEditingActivity(activity: MultimediaEditFieldActivity) {
super.setEditingActivity(activity)
val registry = mActivity.activityResultRegistry
val registry = this._activity.activityResultRegistry
selectMediaLauncher = registry.register(SELECT_MEDIA_LAUNCHER_KEY, ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode != Activity.RESULT_CANCELED) {
executeSafe(mActivity, "handleMediaSelection:unhandled") {
executeSafe(this._activity, "handleMediaSelection:unhandled") {
handleMediaSelection(result.data!!)
}
}
@ -117,7 +117,7 @@ class BasicMediaClipFieldController : FieldControllerBase(), IFieldController {
// Get information about the selected document
val queryColumns = arrayOf(MediaStore.MediaColumns.DISPLAY_NAME, MediaStore.MediaColumns.SIZE, MediaStore.MediaColumns.MIME_TYPE)
var mediaClipFullNameParts: Array<String>
mActivity.contentResolver.query(selectedClip!!, queryColumns, null, null, null).use { cursor ->
_activity.contentResolver.query(selectedClip!!, queryColumns, null, null, null).use { cursor ->
if (cursor == null) {
showThemedToast(
AnkiDroidApp.instance.applicationContext,
@ -167,12 +167,12 @@ class BasicMediaClipFieldController : FieldControllerBase(), IFieldController {
// Copy file contents into new temp file. Possibly check file size first and warn if large?
try {
mActivity.contentResolver.openInputStream(selectedClip).use { inputStream ->
_activity.contentResolver.openInputStream(selectedClip).use { inputStream ->
CompatHelper.compat.copyFile(inputStream!!, clipCopy.absolutePath)
// If everything worked, hand off the information
mField.hasTemporaryMedia = true
mField.audioPath = clipCopy.absolutePath
_field.hasTemporaryMedia = true
_field.audioPath = clipCopy.absolutePath
tvAudioClip.text = clipCopy.name
tvAudioClip.visibility = View.VISIBLE
}

View File

@ -35,16 +35,16 @@ import com.ichi2.ui.FixedEditText
* Controllers work with the edit field activity and create UI on it to edit a field.
*/
class BasicTextFieldController : FieldControllerBase(), IFieldController, DialogInterface.OnClickListener {
private lateinit var mEditText: EditText
private lateinit var editText: EditText
// This is used to copy from another field value to this field
private lateinit var mPossibleClones: ArrayList<String>
private lateinit var possibleClones: ArrayList<String>
override fun createUI(context: Context, layout: LinearLayout) {
mEditText = FixedEditText(mActivity)
mEditText.minLines = 3
mEditText.setText(mField.text)
layout.addView(mEditText, LinearLayout.LayoutParams.MATCH_PARENT)
val layoutTools = LinearLayout(mActivity)
editText = FixedEditText(_activity)
editText.minLines = 3
editText.setText(_field.text)
layout.addView(editText, LinearLayout.LayoutParams.MATCH_PARENT)
val layoutTools = LinearLayout(_activity)
layoutTools.orientation = LinearLayout.HORIZONTAL
layout.addView(layoutTools)
val p = LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.MATCH_PARENT, 1F)
@ -53,14 +53,14 @@ class BasicTextFieldController : FieldControllerBase(), IFieldController, Dialog
}
private fun gtxt(id: Int): String {
return mActivity.getText(id).toString()
return _activity.getText(id).toString()
}
private fun createClearButton(layoutTools: LinearLayout, p: LinearLayout.LayoutParams) {
val clearButton = Button(mActivity)
val clearButton = Button(_activity)
clearButton.text = gtxt(R.string.multimedia_editor_text_field_editing_clear)
layoutTools.addView(clearButton, p)
clearButton.setOnClickListener { mEditText.setText("") }
clearButton.setOnClickListener { editText.setText("") }
}
/**
@ -70,23 +70,23 @@ class BasicTextFieldController : FieldControllerBase(), IFieldController, Dialog
*/
private fun createCloneButton(layoutTools: LinearLayout, p: LinearLayout.LayoutParams) {
// Makes sense only for two and more fields
if (mNote.numberOfFields > 1) {
if (_note.numberOfFields > 1) {
// Should be more than one text not empty fields for clone to make
// sense
mPossibleClones = ArrayList(mNote.numberOfFields)
possibleClones = ArrayList(_note.numberOfFields)
var numTextFields = 0
for (i in 0 until mNote.numberOfFields) {
for (i in 0 until _note.numberOfFields) {
// Sort out non text and empty fields
val curField = mNote.getField(i) ?: continue
val curField = _note.getField(i) ?: continue
if (curField.type !== EFieldType.TEXT) {
continue
}
val currFieldText = curField.text ?: continue
if (currFieldText.isEmpty() || currFieldText.contentEquals(mField.text)) {
if (currFieldText.isEmpty() || currFieldText.contentEquals(_field.text)) {
continue
}
// collect clone sources
mPossibleClones.add(currFieldText)
possibleClones.add(currFieldText)
numTextFields++
}
@ -94,16 +94,16 @@ class BasicTextFieldController : FieldControllerBase(), IFieldController, Dialog
if (numTextFields < 1) {
return
}
val btnOtherField = Button(mActivity)
val btnOtherField = Button(_activity)
btnOtherField.text = gtxt(R.string.multimedia_editor_text_field_editing_clone)
layoutTools.addView(btnOtherField, p)
val controller = this
btnOtherField.setOnClickListener {
val fragment = PickStringDialogFragment()
fragment.setChoices(mPossibleClones)
fragment.setChoices(possibleClones)
fragment.setOnclickListener(controller)
fragment.setTitle(gtxt(R.string.multimedia_editor_text_field_editing_clone_source))
fragment.show(mActivity.supportFragmentManager, "pick.clone")
fragment.show(_activity.supportFragmentManager, "pick.clone")
}
}
}
@ -114,19 +114,19 @@ class BasicTextFieldController : FieldControllerBase(), IFieldController, Dialog
// When Done button is clicked
override fun onDone() {
mField.text = mEditText.text.toString()
_field.text = editText.text.toString()
}
// This is when the dialog for clone ends
override fun onClick(dialog: DialogInterface, which: Int) {
mEditText.setText(mPossibleClones[which])
editText.setText(possibleClones[which])
}
/**
* @param text A short cut to show a toast
*/
private fun showToast(text: CharSequence) {
showThemedToast(mActivity, text, true)
showThemedToast(_activity, text, true)
}
override fun onDestroy() {

View File

@ -23,33 +23,32 @@ import com.ichi2.anki.multimediacard.IMultimediaEditableNote
import com.ichi2.anki.multimediacard.activity.MultimediaEditFieldActivity
import com.ichi2.utils.KotlinCleanup
@KotlinCleanup("remove hungarian notation")
@Suppress("VariableNamingDetector")
@Suppress("PropertyName") // issues with overriding `setActivity` etc...
abstract class FieldControllerBase : IFieldController {
@KotlinCleanup("transform mActivity into a property")
protected lateinit var mActivity: MultimediaEditFieldActivity
protected lateinit var mField: IField
protected lateinit var mNote: IMultimediaEditableNote
protected var mIndex = 0
@KotlinCleanup("transform into a property")
protected lateinit var _activity: MultimediaEditFieldActivity
protected lateinit var _field: IField
protected lateinit var _note: IMultimediaEditableNote
protected var index = 0
override fun setField(field: IField) {
mField = field
this._field = field
}
override fun setNote(note: IMultimediaEditableNote) {
mNote = note
this._note = note
}
override fun setFieldIndex(index: Int) {
mIndex = index
this.index = index
}
override fun setEditingActivity(activity: MultimediaEditFieldActivity) {
mActivity = activity
this._activity = activity
}
fun getActivity(): MultimediaEditFieldActivity {
return mActivity
return _activity
}
override fun loadInstanceState(savedInstanceState: Bundle?) { /* Default implementation does nothing */

View File

@ -33,14 +33,14 @@ import java.util.*
class MultimediaEditableNote : IMultimediaEditableNote {
override var isModified = false
private set
private var mFields: ArrayList<IField?>? = null
private var fields: ArrayList<IField?>? = null
var modelId: NoteTypeId = 0
/**
* Field values in the note editor, before any editing has taken place
* These values should not be modified
*/
private var mInitialFields: ArrayList<IField?>? = null
private var initialFields: ArrayList<IField?>? = null
private fun setThisModified() {
isModified = true
}
@ -55,10 +55,10 @@ class MultimediaEditableNote : IMultimediaEditableNote {
private val fieldsPrivate: ArrayList<IField?>
get() {
if (mFields == null) {
mFields = ArrayList(0)
if (fields == null) {
fields = ArrayList(0)
}
return mFields!!
return fields!!
}
override val numberOfFields: Int
get() = fieldsPrivate.size
@ -88,17 +88,17 @@ class MultimediaEditableNote : IMultimediaEditableNote {
}
fun freezeInitialFieldValues() {
mInitialFields = ArrayList()
for (f in mFields!!) {
mInitialFields!!.add(cloneField(f))
initialFields = ArrayList()
for (f in fields!!) {
initialFields!!.add(cloneField(f))
}
}
override val initialFieldCount: Int
get() = mInitialFields!!.size
get() = initialFields!!.size
override fun getInitialField(index: Int): IField? {
return cloneField(mInitialFields!![index])
return cloneField(initialFields!![index])
}
private fun cloneField(f: IField?): IField? {

View File

@ -46,34 +46,34 @@ class DeckAdapter(private val layoutInflater: LayoutInflater, context: Context)
/** The non-collapsed subset of the deck tree that matches the current search. */
private var filteredDeckList: List<DeckNode> = ArrayList()
private val mZeroCountColor: Int
private val mNewCountColor: Int
private val mLearnCountColor: Int
private val mReviewCountColor: Int
private val mRowCurrentDrawable: Int
private val mDeckNameDefaultColor: Int
private val mDeckNameDynColor: Int
private val mExpandImage: Drawable?
private val mCollapseImage: Drawable?
private val zeroCountColor: Int
private val newCountColor: Int
private val learnCountColor: Int
private val reviewCountColor: Int
private val rowCurrentDrawable: Int
private val deckNameDefaultColor: Int
private val deckNameDynColor: Int
private val expandImage: Drawable?
private val collapseImage: Drawable?
private var currentDeckId: DeckId = 0
// Listeners
private var mDeckClickListener: View.OnClickListener? = null
private var mDeckExpanderClickListener: View.OnClickListener? = null
private var mDeckLongClickListener: OnLongClickListener? = null
private var mCountsClickListener: View.OnClickListener? = null
private var deckClickListener: View.OnClickListener? = null
private var deckExpanderClickListener: View.OnClickListener? = null
private var deckLongClickListener: OnLongClickListener? = null
private var countsClickListener: View.OnClickListener? = null
// Totals accumulated as each deck is processed
private var mNew = 0
private var mLrn = 0
private var mRev = 0
private var mNumbersComputed = false
private var new = 0
private var lrn = 0
private var rev = 0
private var numbersComputed = false
// Flags
private var mHasSubdecks = false
private var hasSubdecks = false
// Whether we have a background (so some items should be partially transparent).
private var mPartiallyTransparentForBackground = false
private var partiallyTransparentForBackground = false
// ViewHolder class to save inflated views for recycling
class ViewHolder(v: View) : RecyclerView.ViewHolder(v) {
@ -99,24 +99,24 @@ class DeckAdapter(private val layoutInflater: LayoutInflater, context: Context)
}
fun setDeckClickListener(listener: View.OnClickListener?) {
mDeckClickListener = listener
deckClickListener = listener
}
fun setCountsClickListener(listener: View.OnClickListener?) {
mCountsClickListener = listener
countsClickListener = listener
}
fun setDeckExpanderClickListener(listener: View.OnClickListener?) {
mDeckExpanderClickListener = listener
deckExpanderClickListener = listener
}
fun setDeckLongClickListener(listener: OnLongClickListener?) {
mDeckLongClickListener = listener
deckLongClickListener = listener
}
/** Sets whether the control should have partial transparency to allow a background to be seen */
fun enablePartialTransparencyForBackground(isTransparent: Boolean) {
mPartiallyTransparentForBackground = isTransparent
partiallyTransparentForBackground = isTransparent
}
private val mutex = Mutex()
@ -131,12 +131,12 @@ class DeckAdapter(private val layoutInflater: LayoutInflater, context: Context)
// and do I/O inside it. Better to calculate the new lists outside the lock, then swap
mutex.withLock {
deckTree = node
mHasSubdecks = node.children.any { it.children.any() }
hasSubdecks = node.children.any { it.children.any() }
currentDeckId = withCol { decks.current().optLong("id") }
mRev = node.revCount
mLrn = node.lrnCount
mNew = node.newCount
mNumbersComputed = true
rev = node.revCount
lrn = node.lrnCount
new = node.newCount
numbersComputed = true
// Filtering performs notifyDataSetChanged after the async work is complete
getFilter()?.filter(filter)
}
@ -159,7 +159,7 @@ class DeckAdapter(private val layoutInflater: LayoutInflater, context: Context)
// Set the expander icon and padding according to whether or not there are any subdecks
val deckLayout = holder.deckLayout
val rightPadding = deckLayout.resources.getDimension(R.dimen.deck_picker_right_padding).toInt()
if (mHasSubdecks) {
if (hasSubdecks) {
val smallPadding = deckLayout.resources.getDimension(R.dimen.deck_picker_left_padding_small).toInt()
deckLayout.setPadding(smallPadding, 0, rightPadding, 0)
holder.deckExpander.visibility = View.VISIBLE
@ -172,16 +172,16 @@ class DeckAdapter(private val layoutInflater: LayoutInflater, context: Context)
}
if (node.children.isNotEmpty()) {
holder.deckExpander.tag = node.did
holder.deckExpander.setOnClickListener(mDeckExpanderClickListener)
holder.deckExpander.setOnClickListener(deckExpanderClickListener)
} else {
holder.deckExpander.isClickable = false
holder.deckExpander.setOnClickListener(null)
}
holder.deckLayout.setBackgroundResource(mRowCurrentDrawable)
holder.deckLayout.setBackgroundResource(rowCurrentDrawable)
// Set background colour. The current deck has its own color
if (isCurrentlySelectedDeck(node)) {
holder.deckLayout.setBackgroundResource(mRowCurrentDrawable)
if (mPartiallyTransparentForBackground) {
holder.deckLayout.setBackgroundResource(rowCurrentDrawable)
if (partiallyTransparentForBackground) {
setBackgroundAlpha(holder.deckLayout, SELECTED_DECK_ALPHA_AGAINST_BACKGROUND)
}
} else {
@ -196,27 +196,27 @@ class DeckAdapter(private val layoutInflater: LayoutInflater, context: Context)
val filtered =
node.filtered
if (filtered) {
holder.deckName.setTextColor(mDeckNameDynColor)
holder.deckName.setTextColor(deckNameDynColor)
} else {
holder.deckName.setTextColor(mDeckNameDefaultColor)
holder.deckName.setTextColor(deckNameDefaultColor)
}
// Set the card counts and their colors
holder.deckNew.text = node.newCount.toString()
holder.deckNew.setTextColor(if (node.newCount == 0) mZeroCountColor else mNewCountColor)
holder.deckNew.setTextColor(if (node.newCount == 0) zeroCountColor else newCountColor)
holder.deckLearn.text = node.lrnCount.toString()
holder.deckLearn.setTextColor(if (node.lrnCount == 0) mZeroCountColor else mLearnCountColor)
holder.deckLearn.setTextColor(if (node.lrnCount == 0) zeroCountColor else learnCountColor)
holder.deckRev.text = node.revCount.toString()
holder.deckRev.setTextColor(if (node.revCount == 0) mZeroCountColor else mReviewCountColor)
holder.deckRev.setTextColor(if (node.revCount == 0) zeroCountColor else reviewCountColor)
// Store deck ID in layout's tag for easy retrieval in our click listeners
holder.deckLayout.tag = node.did
holder.countsLayout.tag = node.did
// Set click listeners
holder.deckLayout.setOnClickListener(mDeckClickListener)
holder.deckLayout.setOnLongClickListener(mDeckLongClickListener)
holder.countsLayout.setOnClickListener(mCountsClickListener)
holder.deckLayout.setOnClickListener(deckClickListener)
holder.deckLayout.setOnLongClickListener(deckLongClickListener)
holder.countsLayout.setOnClickListener(countsClickListener)
}
private fun setBackgroundAlpha(view: View, alphaPercentage: Double) {
@ -239,10 +239,10 @@ class DeckAdapter(private val layoutInflater: LayoutInflater, context: Context)
if (node.children.isNotEmpty()) {
expander.importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_YES
if (node.collapsed) {
expander.setImageDrawable(mExpandImage)
expander.setImageDrawable(expandImage)
expander.contentDescription = expander.context.getString(R.string.expand)
} else {
expander.setImageDrawable(mCollapseImage)
expander.setImageDrawable(collapseImage)
expander.contentDescription = expander.context.getString(R.string.collapse)
}
} else {
@ -275,8 +275,8 @@ class DeckAdapter(private val layoutInflater: LayoutInflater, context: Context)
}
val due: Int?
get() = if (mNumbersComputed) {
mNew + mLrn + mRev
get() = if (numbersComputed) {
new + lrn + rev
} else {
null
}
@ -324,17 +324,17 @@ class DeckAdapter(private val layoutInflater: LayoutInflater, context: Context)
R.attr.collapseRef
)
val ta = context.obtainStyledAttributes(attrs)
mZeroCountColor = ta.getColor(0, context.getColor(R.color.black))
mNewCountColor = ta.getColor(1, context.getColor(R.color.black))
mLearnCountColor = ta.getColor(2, context.getColor(R.color.black))
mReviewCountColor = ta.getColor(3, context.getColor(R.color.black))
mRowCurrentDrawable = ta.getResourceId(4, 0)
mDeckNameDefaultColor = ta.getColor(5, context.getColor(R.color.black))
mDeckNameDynColor = ta.getColor(6, context.getColor(R.color.material_blue_A700))
mExpandImage = ta.getDrawable(7)
mExpandImage!!.isAutoMirrored = true
mCollapseImage = ta.getDrawable(8)
mCollapseImage!!.isAutoMirrored = true
zeroCountColor = ta.getColor(0, context.getColor(R.color.black))
newCountColor = ta.getColor(1, context.getColor(R.color.black))
learnCountColor = ta.getColor(2, context.getColor(R.color.black))
reviewCountColor = ta.getColor(3, context.getColor(R.color.black))
rowCurrentDrawable = ta.getResourceId(4, 0)
deckNameDefaultColor = ta.getColor(5, context.getColor(R.color.black))
deckNameDynColor = ta.getColor(6, context.getColor(R.color.material_blue_A700))
expandImage = ta.getDrawable(7)
expandImage!!.isAutoMirrored = true
collapseImage = ta.getDrawable(8)
collapseImage!!.isAutoMirrored = true
ta.recycle()
}
}

View File

@ -41,7 +41,7 @@ fun DeckPicker.performAsyncOperation(
operation: AsyncOperation,
channel: Channel
) {
if (mActivityPaused) {
if (activityPaused) {
sendNotificationForAsyncOperation(operation, channel)
return
}

View File

@ -86,7 +86,7 @@ class AudioRecordingController :
override fun createUI(context: Context, layout: LinearLayout) {
audioRecorder = AudioRecorder()
if (inEditField) {
val origAudioPath = this.mField.audioPath
val origAudioPath = this._field.audioPath
var bExist = false
if (origAudioPath != null) {
val f = File(origAudioPath)
@ -96,7 +96,7 @@ class AudioRecordingController :
}
}
if (!bExist) {
tempAudioPath = generateTempAudioFile(mActivity)
tempAudioPath = generateTempAudioFile(_activity)
}
}
@ -121,8 +121,8 @@ class AudioRecordingController :
label.gravity = Gravity.CENTER_HORIZONTAL
previewLayout.addView(label)
var hasTextContents = false
for (i in 0 until mNote.initialFieldCount) {
val field = mNote.getInitialField(i)
for (i in 0 until _note.initialFieldCount) {
val field = _note.getInitialField(i)
FixedTextView(this).apply {
text = field?.text
textSize = 16f
@ -355,8 +355,8 @@ class AudioRecordingController :
}
private fun saveRecording() {
mField.audioPath = tempAudioPath
mField.hasTemporaryMedia = true
_field.audioPath = tempAudioPath
_field.hasTemporaryMedia = true
}
fun stopAndSaveRecording() {

View File

@ -460,7 +460,7 @@ open class Card : Cloneable {
open class Cache : Cloneable {
val col: Collection
val id: Long
private var mCard: Card? = null
private var _card: Card? = null
constructor(col: Collection, id: Long) {
this.col = col
@ -471,7 +471,7 @@ open class Card : Cloneable {
protected constructor(cache: Cache) {
col = cache.col
this.id = cache.id
mCard = cache.mCard
_card = cache._card
}
/**
@ -481,16 +481,16 @@ open class Card : Cloneable {
@get:Synchronized
val card: Card
get() {
if (mCard == null) {
mCard = col.getCard(this.id)
if (_card == null) {
_card = col.getCard(this.id)
}
return mCard!!
return _card!!
}
/** Next access to card will reload the card from the database. */
@Synchronized
open fun reload() {
mCard = null
_card = null
}
override fun hashCode(): Int {

View File

@ -109,8 +109,8 @@ open class Collection(
lateinit var sched: Scheduler
protected set
private var mStartTime: Long
private var mStartReps: Int
private var startTime: Long
private var startReps: Int
val mod: Long
get() = db.queryLongScalar("select mod from col")
@ -131,15 +131,15 @@ open class Collection(
var ls: Long = 0
// END: SQL table columns
private var mLogHnd: PrintWriter? = null
private var logHnd: PrintWriter? = null
init {
media = Media(this)
tags = Tags(this)
val created = reopen()
log(path, VersionUtils.pkgVersionName)
mStartReps = 0
mStartTime = 0
startReps = 0
startTime = 0
_loadScheduler()
if (created) {
sched.useNewTimezoneCode()
@ -457,8 +457,8 @@ open class Collection(
*/
fun startTimebox() {
mStartTime = TimeManager.time.intTime()
mStartReps = sched.reps
startTime = TimeManager.time.intTime()
startReps = sched.reps
}
data class TimeboxReached(val secs: Int, val reps: Int)
@ -470,12 +470,12 @@ open class Collection(
// timeboxing disabled
return null
}
val elapsed = TimeManager.time.intTime() - mStartTime
val elapsed = TimeManager.time.intTime() - startTime
val limit = sched.timeboxSecs()
return if (elapsed > limit) {
TimeboxReached(
limit,
sched.reps - mStartReps
sched.reps - startReps
).also {
startTimebox()
}
@ -592,7 +592,7 @@ open class Collection(
}
private fun writeLog(s: String) {
mLogHnd?.let {
logHnd?.let {
try {
it.println(s)
} catch (e: Exception) {
@ -616,7 +616,7 @@ open class Collection(
}
lpath.renameTo(lpath2)
}
mLogHnd = PrintWriter(BufferedWriter(FileWriter(lpath, true)), true)
logHnd = PrintWriter(BufferedWriter(FileWriter(lpath, true)), true)
} catch (e: IOException) {
// turn off logging if we can't open the log file
Timber.e("Failed to open collection.log file - disabling logging")
@ -627,8 +627,8 @@ open class Collection(
private fun _closeLog() {
if (!debugLog) return
Timber.i("Closing Collection Log")
mLogHnd?.close()
mLogHnd = null
logHnd?.close()
logHnd = null
}
/**

View File

@ -48,11 +48,12 @@ import java.util.*
* This technique can be used with an [android.app.Activity] class, not just
* [android.preference.PreferenceActivity].
*/
@KotlinCleanup("replace _delegate with `field`")
abstract class AppCompatPreferenceActivity<PreferenceHack : AppCompatPreferenceActivity<PreferenceHack>.AbstractPreferenceHack> :
PreferenceActivity(),
CoroutineScope by MainScope(),
SharedPreferences.OnSharedPreferenceChangeListener {
private var mDelegate: AppCompatDelegate? = null
private var _delegate: AppCompatDelegate? = null
fun isColInitialized() = ::col.isInitialized
protected var prefChanged = false
lateinit var unmountReceiver: BroadcastReceiver
@ -264,10 +265,10 @@ abstract class AppCompatPreferenceActivity<PreferenceHack : AppCompatPreferenceA
private val delegate: AppCompatDelegate
get() {
if (mDelegate == null) {
mDelegate = AppCompatDelegate.create(this, null)
if (_delegate == null) {
_delegate = AppCompatDelegate.create(this, null)
}
return mDelegate!! // safe as mDelegate is only initialized here, before being returned
return _delegate!! // safe as mDelegate is only initialized here, before being returned
}
/**

View File

@ -281,7 +281,7 @@ class AbstractFlashcardViewerTest : RobolectricTest() {
controller.pause()
assertThat("disabled after pause", viewer.automaticAnswer.isDisabled, equalTo(true))
assertThat("no auto answer after pause", viewer.hasAutomaticAnswerQueued(), equalTo(false))
viewer.mOnRenderProcessGoneDelegate.onRenderProcessGone(viewer.webView!!, mock(RenderProcessGoneDetail::class.java))
viewer.onRenderProcessGoneDelegate.onRenderProcessGone(viewer.webView!!, mock(RenderProcessGoneDetail::class.java))
assertThat("no auto answer after onRenderProcessGone when paused", viewer.hasAutomaticAnswerQueued(), equalTo(false))
}

View File

@ -691,7 +691,7 @@ class DeckPickerTest : RobolectricTest() {
assertThat("unbury is not visible: deck has no cards", !col.sched.haveBuriedInCurrentDeck())
deckPicker {
assertThat("deck focus is set", mFocusedDeck, equalTo(emptyDeck))
assertThat("deck focus is set", focusedDeck, equalTo(emptyDeck))
// ACT: open up the Deck Context Menu
val deckToClick = recyclerView.children.single {
@ -701,7 +701,7 @@ class DeckPickerTest : RobolectricTest() {
// ASSERT
assertThat("unbury is visible: one card is buried", col.sched.haveBuriedInCurrentDeck())
assertThat("deck focus has changed", mFocusedDeck, equalTo(deckWithCards))
assertThat("deck focus has changed", focusedDeck, equalTo(deckWithCards))
}
}

View File

@ -412,7 +412,7 @@ class ReviewerKeyboardInputTest : RobolectricTest() {
fun displayingAnswer(): KeyboardInputTestReviewer {
val keyboardInputTestReviewer = KeyboardInputTestReviewer()
displayAnswer = true
keyboardInputTestReviewer.mProcessor.setup()
keyboardInputTestReviewer.processor.setup()
return keyboardInputTestReviewer
}
@ -420,7 +420,7 @@ class ReviewerKeyboardInputTest : RobolectricTest() {
fun displayingQuestion(): KeyboardInputTestReviewer {
val keyboardInputTestReviewer = KeyboardInputTestReviewer()
displayAnswer = false
keyboardInputTestReviewer.mProcessor.setup()
keyboardInputTestReviewer.processor.setup()
return keyboardInputTestReviewer
}
}

View File

@ -419,4 +419,4 @@ class ReviewerTest : RobolectricTest() {
}
}
val Reviewer.isDisplayingMark: Boolean get() = this.mCardMarker!!.isDisplayingMark
val Reviewer.isDisplayingMark: Boolean get() = this.cardMarker!!.isDisplayingMark

View File

@ -46,8 +46,8 @@ import java.util.*
*/
@Suppress("unused")
public class AddContentApi(context: Context) {
private val mContext: Context = context.applicationContext
private val mResolver: ContentResolver = mContext.contentResolver
private val context: Context = context.applicationContext
private val resolver: ContentResolver = this.context.contentResolver
/**
* Create a new note with specified fields, tags, and model and place it in the specified deck.
@ -78,16 +78,16 @@ public class AddContentApi(context: Context) {
}
private fun addNoteForContentValues(deckId: Long, values: ContentValues): Uri? {
val newNoteUri = mResolver.insert(Note.CONTENT_URI, values) ?: return null
val newNoteUri = resolver.insert(Note.CONTENT_URI, values) ?: return null
// Move cards to specified deck
val cardsUri = Uri.withAppendedPath(newNoteUri, "cards")
val cardsQuery = mResolver.query(cardsUri, null, null, null, null) ?: return null
val cardsQuery = resolver.query(cardsUri, null, null, null, null) ?: return null
cardsQuery.use { cardsCursor ->
while (cardsCursor.moveToNext()) {
val ord = cardsCursor.getString(cardsCursor.getColumnIndex(Card.CARD_ORD))
val cardValues = ContentValues().apply { put(Card.DECK_ID, deckId) }
val cardUri = Uri.withAppendedPath(Uri.withAppendedPath(newNoteUri, "cards"), ord)
mResolver.update(cardUri, cardValues, null, null)
resolver.update(cardUri, cardValues, null, null)
}
}
return newNoteUri
@ -167,7 +167,7 @@ public class AddContentApi(context: Context) {
put(AnkiMedia.PREFERRED_NAME, preferredName.replace(" ", "_"))
}
return try {
val returnUri = mResolver.insert(AnkiMedia.CONTENT_URI, contentValues)
val returnUri = resolver.insert(AnkiMedia.CONTENT_URI, contentValues)
// get the filename from Uri, return [sound:%s] % file.getName()
val fname = File(returnUri!!.path!!).toString()
formatMediaName(fname, mimeType)
@ -244,7 +244,7 @@ public class AddContentApi(context: Context) {
*/
public fun getNote(noteId: Long): NoteInfo? {
val noteUri = Uri.withAppendedPath(Note.CONTENT_URI, noteId.toString())
val query = mResolver.query(noteUri, PROJECTION, null, null, null) ?: return null
val query = resolver.query(noteUri, PROJECTION, null, null, null) ?: return null
return query.use { cursor ->
if (!cursor.moveToNext()) {
null
@ -260,7 +260,7 @@ public class AddContentApi(context: Context) {
if (fields != null) put(Note.FLDS, Utils.joinFields(fields))
if (tags != null) put(Note.TAGS, Utils.joinTags(tags))
}
val numRowsUpdated = mResolver.update(contentUri, values, null, null)
val numRowsUpdated = resolver.update(contentUri, values, null, null)
// provider doesn't check whether fields actually changed, so just returns number of notes with id == noteId
return numRowsUpdated > 0
}
@ -281,7 +281,7 @@ public class AddContentApi(context: Context) {
// Build map of HTML for each generated card
val cards: MutableMap<String, Map<String, String>> = HashMap()
val cardsUri = Uri.withAppendedPath(newNoteUri, "cards")
val cardsQuery = mResolver.query(cardsUri, null, null, null, null) ?: return null
val cardsQuery = resolver.query(cardsUri, null, null, null, null) ?: return null
cardsQuery.use { cardsCursor ->
while (cardsCursor.moveToNext()) {
// add question and answer for each card to map
@ -295,7 +295,7 @@ public class AddContentApi(context: Context) {
}
}
// Delete the note
mResolver.delete(newNoteUri!!, null, null)
resolver.delete(newNoteUri!!, null, null)
return cards
}
@ -371,7 +371,7 @@ public class AddContentApi(context: Context) {
put(Model.DECK_ID, did)
put(Model.SORT_FIELD_INDEX, sortf)
}
val modelUri = mResolver.insert(Model.CONTENT_URI, values) ?: return null
val modelUri = resolver.insert(Model.CONTENT_URI, values) ?: return null
// Set the remaining template parameters
val templatesUri = Uri.withAppendedPath(modelUri, "templates")
for (i in cards.indices) {
@ -382,7 +382,7 @@ public class AddContentApi(context: Context) {
put(CardTemplate.ANSWER_FORMAT, afmt[i])
put(CardTemplate.ANSWER_FORMAT, afmt[i])
}
mResolver.update(uri, values, null, null)
resolver.update(uri, values, null, null)
}
return modelUri.lastPathSegment!!.toLong()
} // Get the current model
@ -395,7 +395,7 @@ public class AddContentApi(context: Context) {
get() {
// Get the current model
val uri = Uri.withAppendedPath(Model.CONTENT_URI, Model.CURRENT_MODEL_ID)
val singleModelQuery = mResolver.query(uri, null, null, null, null) ?: return -1L
val singleModelQuery = resolver.query(uri, null, null, null, null) ?: return -1L
return singleModelQuery.use { singleModelCursor ->
singleModelCursor.moveToFirst()
singleModelCursor.getLong(singleModelCursor.getColumnIndex(Model._ID))
@ -410,7 +410,7 @@ public class AddContentApi(context: Context) {
public fun getFieldList(modelId: Long): Array<String>? {
// Get the current model
val uri = Uri.withAppendedPath(Model.CONTENT_URI, modelId.toString())
val modelQuery = mResolver.query(uri, null, null, null, null) ?: return null
val modelQuery = resolver.query(uri, null, null, null, null) ?: return null
var splitFlds: Array<String>? = null
modelQuery.use { modelCursor ->
if (modelCursor.moveToNext()) {
@ -437,7 +437,7 @@ public class AddContentApi(context: Context) {
public fun getModelList(minNumFields: Int): Map<Long, String>? {
// Get the current model
val allModelsQuery =
mResolver.query(Model.CONTENT_URI, null, null, null, null)
resolver.query(Model.CONTENT_URI, null, null, null, null)
?: return null
val models: MutableMap<Long, String> = HashMap()
allModelsQuery.use { allModelsCursor ->
@ -470,7 +470,7 @@ public class AddContentApi(context: Context) {
public fun addNewDeck(deckName: String): Long? {
// Create a new note
val values = ContentValues().apply { put(Deck.DECK_NAME, deckName) }
val newDeckUri = mResolver.insert(Deck.CONTENT_ALL_URI, values)
val newDeckUri = resolver.insert(Deck.CONTENT_ALL_URI, values)
return if (newDeckUri != null) {
newDeckUri.lastPathSegment!!.toLong()
} else {
@ -484,7 +484,7 @@ public class AddContentApi(context: Context) {
*/
public val selectedDeckName: String?
get() {
val selectedDeckQuery = mResolver.query(
val selectedDeckQuery = resolver.query(
Deck.CONTENT_SELECTED_URI,
null,
null,
@ -508,7 +508,7 @@ public class AddContentApi(context: Context) {
get() {
// Get the current model
val allDecksQuery =
mResolver.query(Deck.CONTENT_ALL_URI, null, null, null, null) ?: return null
resolver.query(Deck.CONTENT_ALL_URI, null, null, null, null) ?: return null
val decks: MutableMap<Long, String> = HashMap()
allDecksQuery.use { allDecksCursor ->
while (allDecksCursor.moveToNext()) {
@ -547,14 +547,14 @@ public class AddContentApi(context: Context) {
// GET_META_DATA seems to work anyway
val info =
if (Build.VERSION.SDK_INT >= 33) {
mContext.packageManager.resolveContentProvider(
context.packageManager.resolveContentProvider(
FlashCardsContract.AUTHORITY,
PackageManager.ComponentInfoFlags.of(
PackageManager.GET_META_DATA.toLong()
)
)
} else {
mContext.packageManager.resolveContentProvider(
context.packageManager.resolveContentProvider(
FlashCardsContract.AUTHORITY,
PackageManager.GET_META_DATA
)
@ -571,7 +571,7 @@ public class AddContentApi(context: Context) {
}
private fun hasReadWritePermission(): Boolean =
mContext.checkPermission(
context.checkPermission(
READ_WRITE_PERMISSION,
Process.myPid(),
Process.myUid()
@ -615,7 +615,7 @@ public class AddContentApi(context: Context) {
override fun queryNotes(modelId: Long): Cursor? {
val modelName = getModelName(modelId) ?: return null
val queryFormat = "note:\"$modelName\""
return mResolver.query(
return resolver.query(
Note.CONTENT_URI,
PROJECTION,
queryFormat,
@ -639,7 +639,7 @@ public class AddContentApi(context: Context) {
val queryFormat = "${modelFieldList[0]}:\"%%s\" note:\"$modelName\""
for (outputPos in keys.indices) {
val selection = String.format(queryFormat, keys[outputPos])
val query = mResolver.query(
val query = resolver.query(
Note.CONTENT_URI,
PROJECTION,
selection,
@ -677,7 +677,7 @@ public class AddContentApi(context: Context) {
private inner class CompatV2 : CompatV1() {
override fun queryNotes(modelId: Long): Cursor? {
return mResolver.query(
return resolver.query(
Note.CONTENT_URI_V2,
PROJECTION,
String.format(Locale.US, "%s=%d", Note.MID, modelId),
@ -691,7 +691,7 @@ public class AddContentApi(context: Context) {
Note.DECK_ID_QUERY_PARAM,
deckId.toString()
)
return mResolver.bulkInsert(builder.build(), valuesArr)
return resolver.bulkInsert(builder.build(), valuesArr)
}
override fun findDuplicateNotes(
@ -718,7 +718,7 @@ public class AddContentApi(context: Context) {
Note.CSUM,
csums.joinToString(separator = ",")
)
val notesTableQuery = mResolver.query(
val notesTableQuery = resolver.query(
Note.CONTENT_URI_V2,
PROJECTION,
sel,