forked from ankidroid/Anki-Android
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathNoteEditorActivity.kt
More file actions
162 lines (146 loc) · 6.92 KB
/
NoteEditorActivity.kt
File metadata and controls
162 lines (146 loc) · 6.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
/*
* Copyright (c) 2025 Hari Srinivasan <harisrini21@gmail.com>
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 3 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.ichi2.anki
import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.fragment.app.Fragment
import androidx.fragment.app.commit
import com.ichi2.anki.android.input.ShortcutGroup
import com.ichi2.anki.android.input.ShortcutGroupProvider
import com.ichi2.anki.libanki.Collection
import com.ichi2.anki.noteeditor.NoteEditorLauncher
import com.ichi2.anki.snackbar.BaseSnackbarBuilderProvider
import com.ichi2.anki.snackbar.SnackbarBuilder
import timber.log.Timber
import kotlin.reflect.KClass
import kotlin.reflect.jvm.jvmName
/**
* To find the actual note Editor, @see [NoteEditorFragment]
* This activity contains the NoteEditorFragment, and, on x-large screens, the previewer fragment.
* It also ensures that changes in the note are transmitted to the previewer
*/
// TODO: Move intent handling to [NoteEditorActivity] from [NoteEditorFragment]
class NoteEditorActivity :
AnkiActivity(),
BaseSnackbarBuilderProvider,
DispatchKeyEventListener,
ShortcutGroupProvider {
override val baseSnackbarBuilder: SnackbarBuilder = { }
lateinit var noteEditorFragment: NoteEditorFragment
override fun onCreate(savedInstanceState: Bundle?) {
if (showedActivityFailedScreen(savedInstanceState)) {
return
}
super.onCreate(savedInstanceState)
if (!ensureStoragePermissions()) {
return
}
setContentView(R.layout.note_editor)
/**
* The [NoteEditorActivity] activity supports multiple note editing workflows using fragments.
* It dynamically chooses the appropriate fragment to load and the arguments to pass to it,
* based on intent extras provided at launch time.
*
* - [FRAGMENT_NAME_EXTRA]: Fully qualified name of the fragment class to instantiate.
* If set to [NoteEditorFragment], the activity initializes it with the arguments in
* [FRAGMENT_ARGS_EXTRA].
*
* - [FRAGMENT_ARGS_EXTRA]: Bundle containing parameters for the fragment (e.g. note ID,
* deck ID, etc.). Used to populate fields or determine editor behavior.
*
* This logic is encapsulated in the [launcher] assignment, which selects the correct
* fragment mode (e.g. add note, edit note) based on intent contents.
*/
val launcher =
if (intent.hasExtra(FRAGMENT_NAME_EXTRA)) {
val fragmentClassName = intent.getStringExtra(FRAGMENT_NAME_EXTRA)
if (fragmentClassName == NoteEditorFragment::class.java.name) {
val fragmentArgs = intent.getBundleExtra(FRAGMENT_ARGS_EXTRA)
if (fragmentArgs != null) {
NoteEditorLauncher.PassArguments(fragmentArgs)
} else {
NoteEditorLauncher.AddNote()
}
} else {
NoteEditorLauncher.AddNote()
}
} else {
// Regular NoteEditor intent handling
intent.getBundleExtra(FRAGMENT_ARGS_EXTRA)?.let { fragmentArgs ->
// If FRAGMENT_ARGS_EXTRA is provided, use it directly
NoteEditorLauncher.PassArguments(fragmentArgs)
} ?: intent.extras?.let { bundle ->
// Check if the bundle contains FRAGMENT_ARGS_EXTRA (for launchers that wrap their args)
bundle.getBundle(FRAGMENT_ARGS_EXTRA)?.let { wrappedFragmentArgs ->
NoteEditorLauncher.PassArguments(wrappedFragmentArgs)
} ?: NoteEditorLauncher.PassArguments(bundle)
} ?: NoteEditorLauncher.AddNote()
}
val existingFragment = supportFragmentManager.findFragmentByTag(FRAGMENT_TAG)
if (existingFragment == null) {
supportFragmentManager.commit {
replace(R.id.note_editor_fragment_frame, NoteEditorFragment.newInstance(launcher), FRAGMENT_TAG)
setReorderingAllowed(true)
/**
* Initializes the noteEditorFragment reference only after the transaction is committed.
* This ensures the fragment is fully created and available in the activity before
* any code attempts to interact with it, preventing potential null reference issues.
*/
runOnCommit {
noteEditorFragment = supportFragmentManager.findFragmentByTag(FRAGMENT_TAG) as NoteEditorFragment
}
}
} else {
noteEditorFragment = existingFragment as NoteEditorFragment
}
startLoadingCollection()
}
override fun onCollectionLoaded(col: Collection) {
super.onCollectionLoaded(col)
Timber.d("onCollectionLoaded()")
registerReceiver()
}
override fun dispatchKeyEvent(event: android.view.KeyEvent): Boolean =
noteEditorFragment.dispatchKeyEvent(event) || super.dispatchKeyEvent(event)
override val shortcuts: ShortcutGroup
get() = noteEditorFragment.shortcuts
companion object {
const val FRAGMENT_ARGS_EXTRA = "fragmentArgs"
const val FRAGMENT_NAME_EXTRA = "fragmentName"
const val FRAGMENT_TAG = "NoteEditorFragmentTag"
/**
* Creates an Intent to launch the NoteEditor activity with a specific fragment class and arguments.
*
* @param context The context from which the intent will be launched
* @param fragmentClass The Kotlin class of the Fragment to instantiate
* @param arguments Optional bundle of arguments to pass to the fragment
* @param intentAction Optional action to set on the intent
* @return An Intent configured to launch NoteEditor with the specified fragment
*/
fun getIntent(
context: Context,
fragmentClass: KClass<out Fragment>,
arguments: Bundle? = null,
intentAction: String? = null,
): Intent =
Intent(context, NoteEditorActivity::class.java).apply {
putExtra(FRAGMENT_NAME_EXTRA, fragmentClass.jvmName)
putExtra(FRAGMENT_ARGS_EXTRA, arguments)
action = intentAction
}
}
}