rename: Android is Inkwell — package, applicationId, uniffi class, assets
Step 4 of milestone 481 (Scribe note 5071: a full rename). - namespace and applicationId com.fabledsword.inkwell; the Kotlin package moves with them, and ktlint re-sorted the imports the rename reordered (checked locally with CI's ktlint 1.4.0 and detekt 1.23.7, both clean) - uniffi: class Inkwell in com.fabledsword.inkwell.core, InkwellApplication, InkwellTheme, Theme.Inkwell, log tags, prefs and work names, client agent inkwell-android - the lane publishes inkwell.apk / inkwell-android.json; fetch-clients, guard-forward, publish-release and write-manifest read the same names A new applicationId is a new app. The old ThoughtSync app keeps its own store and stays installed beside it. Notes cross over by syncing, and the old app is then removed by hand. Kept: the signing keyAlias is still "thoughtsync". It names the key inside the existing keystore, and the key, and so the certificate, are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -134,7 +134,7 @@ jobs:
|
||||
echo "code=$code" >> $GITHUB_OUTPUT
|
||||
|
||||
if [ -n "${ANDROID_KEYSTORE_BASE64:-}" ]; then
|
||||
printf '%s' "$ANDROID_KEYSTORE_BASE64" | base64 -d > /tmp/thoughtsync-release.jks
|
||||
printf '%s' "$ANDROID_KEYSTORE_BASE64" | base64 -d > /tmp/inkwell-release.jks
|
||||
echo "variant=Release" >> $GITHUB_OUTPUT
|
||||
echo "label=release" >> $GITHUB_OUTPUT
|
||||
# DEBUG profile, in a release APK, deliberately — see the note above
|
||||
@@ -143,7 +143,7 @@ jobs:
|
||||
# outright (run 4077). Unpicking that is worth doing and is not worth
|
||||
# blocking signed builds on.
|
||||
echo "profile=debug" >> $GITHUB_OUTPUT
|
||||
echo "keystore=/tmp/thoughtsync-release.jks" >> $GITHUB_OUTPUT
|
||||
echo "keystore=/tmp/inkwell-release.jks" >> $GITHUB_OUTPUT
|
||||
echo "apk=android/app/build/outputs/apk/release/app-release.apk" >> $GITHUB_OUTPUT
|
||||
echo "Signed release build — $version (versionCode $code)"
|
||||
else
|
||||
@@ -167,7 +167,7 @@ jobs:
|
||||
# from the built .so. Run as its own step so a Rust failure is legible as a
|
||||
# Rust failure instead of arriving inside a Gradle stack trace.
|
||||
- name: Build the native library and bindings
|
||||
run: ./gradlew generateUniffiBindings -PTHOUGHTSYNC_CARGO_PROFILE=${{ steps.build.outputs.profile }}
|
||||
run: ./gradlew generateUniffiBindings -PINKWELL_CARGO_PROFILE=${{ steps.build.outputs.profile }}
|
||||
|
||||
# The image's PINNED CLIs, not Gradle plugins. ci-rust-android carries both
|
||||
# (M12 step 3) precisely so this lane needs no second image, and going
|
||||
@@ -193,7 +193,7 @@ jobs:
|
||||
# not exist (run 4082). It costs one extra Kotlin compile and buys the
|
||||
# type-check on the debug variant, which is the one an emulator build
|
||||
# would use.
|
||||
run: ./gradlew testDebugUnitTest -PTHOUGHTSYNC_CARGO_PROFILE=${{ steps.build.outputs.profile }}
|
||||
run: ./gradlew testDebugUnitTest -PINKWELL_CARGO_PROFILE=${{ steps.build.outputs.profile }}
|
||||
|
||||
- name: Assemble the APK
|
||||
env:
|
||||
@@ -203,9 +203,9 @@ jobs:
|
||||
ANDROID_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }}
|
||||
run: |
|
||||
./gradlew assemble${{ steps.build.outputs.variant }} \
|
||||
-PTHOUGHTSYNC_CARGO_PROFILE=${{ steps.build.outputs.profile }} \
|
||||
-PTHOUGHTSYNC_VERSION_NAME=${{ steps.build.outputs.name }} \
|
||||
-PTHOUGHTSYNC_VERSION_CODE=${{ steps.build.outputs.code }}
|
||||
-PINKWELL_CARGO_PROFILE=${{ steps.build.outputs.profile }} \
|
||||
-PINKWELL_VERSION_NAME=${{ steps.build.outputs.name }} \
|
||||
-PINKWELL_VERSION_CODE=${{ steps.build.outputs.code }}
|
||||
|
||||
# Prints the certificate the APK was actually signed with, so the operator
|
||||
# can compare it against the fingerprint recorded when the key was
|
||||
@@ -226,10 +226,10 @@ jobs:
|
||||
if: steps.build.outputs.keystore != ''
|
||||
run: |
|
||||
mkdir -p dist
|
||||
cp "app/build/outputs/apk/release/app-release.apk" dist/thoughtsync.apk
|
||||
size="$(wc -c < dist/thoughtsync.apk | tr -d ' ')"
|
||||
sha="$(sha256sum dist/thoughtsync.apk | cut -d' ' -f1)"
|
||||
cat > dist/thoughtsync-android.json <<JSON
|
||||
cp "app/build/outputs/apk/release/app-release.apk" dist/inkwell.apk
|
||||
size="$(wc -c < dist/inkwell.apk | tr -d ' ')"
|
||||
sha="$(sha256sum dist/inkwell.apk | cut -d' ' -f1)"
|
||||
cat > dist/inkwell-android.json <<JSON
|
||||
{
|
||||
"version_name": "${{ steps.build.outputs.name }}",
|
||||
"version_code": ${{ steps.build.outputs.code }},
|
||||
@@ -237,7 +237,7 @@ jobs:
|
||||
"sha256": "$sha"
|
||||
}
|
||||
JSON
|
||||
cat dist/thoughtsync-android.json
|
||||
cat dist/inkwell-android.json
|
||||
|
||||
# The rolling channel for this branch, the same fixed-tag releases the desktop
|
||||
# bundles use. CI artifacts are per-run and auth-gated, so they are no use as a
|
||||
@@ -276,7 +276,7 @@ jobs:
|
||||
with:
|
||||
# The APK's variant, NOT the Cargo profile — those are the same word
|
||||
# for different things and the profile is pinned to debug (#2810).
|
||||
name: thoughtsync-android-${{ steps.build.outputs.label }}-${{ github.sha }}
|
||||
name: inkwell-android-${{ steps.build.outputs.label }}-${{ github.sha }}
|
||||
path: ${{ steps.build.outputs.apk }}
|
||||
if-no-files-found: error
|
||||
|
||||
|
||||
@@ -141,7 +141,7 @@ val rustInputs =
|
||||
* build, and neither is worth holding signed APKs up for. Scribe #2810.
|
||||
*/
|
||||
val rustProfile =
|
||||
(project.findProperty("THOUGHTSYNC_CARGO_PROFILE") as String?)?.takeIf { it.isNotBlank() }
|
||||
(project.findProperty("INKWELL_CARGO_PROFILE") as String?)?.takeIf { it.isNotBlank() }
|
||||
?: "debug"
|
||||
|
||||
val jniLibsOut = layout.buildDirectory.dir("rustJniLibs")
|
||||
@@ -169,11 +169,11 @@ val generateBindings =
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "com.fabledsword.thoughtsync"
|
||||
namespace = "com.fabledsword.inkwell"
|
||||
compileSdk = 36
|
||||
|
||||
defaultConfig {
|
||||
applicationId = "com.fabledsword.thoughtsync"
|
||||
applicationId = "com.fabledsword.inkwell"
|
||||
// 26 (Android 8, 2017) matches Minstrel and clears the NDK's floor with
|
||||
// room to spare.
|
||||
minSdk = 26
|
||||
@@ -181,9 +181,9 @@ android {
|
||||
// Injected by CI from the git tag + commit count for a release; "dev"
|
||||
// locally so the About screen reads honestly rather than claiming 1.0.
|
||||
val nameOverride =
|
||||
(project.findProperty("THOUGHTSYNC_VERSION_NAME") as String?)?.takeIf { it.isNotBlank() }
|
||||
(project.findProperty("INKWELL_VERSION_NAME") as String?)?.takeIf { it.isNotBlank() }
|
||||
val codeOverride =
|
||||
(project.findProperty("THOUGHTSYNC_VERSION_CODE") as String?)?.toIntOrNull()
|
||||
(project.findProperty("INKWELL_VERSION_CODE") as String?)?.toIntOrNull()
|
||||
versionCode = codeOverride ?: 1
|
||||
versionName = nameOverride ?: "dev"
|
||||
|
||||
@@ -215,7 +215,10 @@ android {
|
||||
// Hardcoded, and NOT a secret: the alias is fixed for the life of
|
||||
// this app and is written into the certificate every install
|
||||
// already carries. Hiding it would buy nothing and stop this file
|
||||
// describing its own signing setup.
|
||||
// describing its own signing setup. It still says `thoughtsync`
|
||||
// after the rename to Inkwell, because it names the key inside the
|
||||
// existing keystore, and renaming it would only stop that key being
|
||||
// found. Same key, so the signing certificate did not change either.
|
||||
keyAlias = "thoughtsync"
|
||||
// PKCS12 cannot hold a key password distinct from the store
|
||||
// password — keytool refuses to set one — so this is the same
|
||||
|
||||
Vendored
+1
-1
@@ -4,4 +4,4 @@
|
||||
# is the worst possible time to learn it.
|
||||
-keep class com.sun.jna.** { *; }
|
||||
-keepclassmembers class * extends com.sun.jna.** { public *; }
|
||||
-keep class com.fabledsword.thoughtsync.core.** { *; }
|
||||
-keep class com.fabledsword.inkwell.core.** { *; }
|
||||
|
||||
@@ -91,13 +91,13 @@
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||
|
||||
<application
|
||||
android:name=".ThoughtSyncApplication"
|
||||
android:name=".InkwellApplication"
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.ThoughtSync"
|
||||
android:theme="@style/Theme.Inkwell"
|
||||
android:usesCleartextTraffic="true">
|
||||
<!--
|
||||
launchMode="singleTop" exists for the SHARE filters below.
|
||||
@@ -115,7 +115,7 @@
|
||||
android:exported="true"
|
||||
android:launchMode="singleTop"
|
||||
android:windowSoftInputMode="adjustResize"
|
||||
android:theme="@style/Theme.ThoughtSync">
|
||||
android:theme="@style/Theme.Inkwell">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
package com.fabledsword.thoughtsync
|
||||
package com.fabledsword.inkwell
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
@@ -42,7 +42,7 @@ import java.io.File
|
||||
* [UpdateReceiver], which is why a failure can be shown rather than guessed at.
|
||||
*/
|
||||
object AppUpdate {
|
||||
private const val TAG = "ThoughtSyncUpdate"
|
||||
private const val TAG = "InkwellUpdate"
|
||||
|
||||
/** This build's versionCode — what the server's is compared against. */
|
||||
fun installedVersionCode(context: Context): Long =
|
||||
@@ -173,5 +173,5 @@ object AppUpdate {
|
||||
.intentSender
|
||||
}
|
||||
|
||||
private const val WRITE_NAME = "thoughtsync-update"
|
||||
private const val WRITE_NAME = "inkwell-update"
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.fabledsword.thoughtsync
|
||||
package com.fabledsword.inkwell
|
||||
|
||||
import android.content.Context
|
||||
|
||||
+9
-9
@@ -1,9 +1,9 @@
|
||||
package com.fabledsword.thoughtsync
|
||||
package com.fabledsword.inkwell
|
||||
|
||||
import android.app.Application
|
||||
import android.util.Log
|
||||
import com.fabledsword.thoughtsync.core.ThoughtSync
|
||||
import com.fabledsword.thoughtsync.core.setClientAgent
|
||||
import com.fabledsword.inkwell.core.Inkwell
|
||||
import com.fabledsword.inkwell.core.setClientAgent
|
||||
|
||||
/**
|
||||
* Opens the shared Rust core once, for the process lifetime.
|
||||
@@ -16,14 +16,14 @@ import com.fabledsword.thoughtsync.core.setClientAgent
|
||||
* removed on uninstall, and never on external media. The core does not guess at
|
||||
* platform paths; Android is the only thing that knows where this is.
|
||||
*/
|
||||
class ThoughtSyncApplication : Application() {
|
||||
class InkwellApplication : Application() {
|
||||
/**
|
||||
* Null only if the store could not be opened — a corrupt or unwritable
|
||||
* database. The UI reports that honestly rather than crashing on first
|
||||
* touch, because a user whose notes won't open needs a message, not a
|
||||
* stack trace.
|
||||
*/
|
||||
var core: ThoughtSync? = null
|
||||
var core: Inkwell? = null
|
||||
private set
|
||||
|
||||
var openFailure: String? = null
|
||||
@@ -34,13 +34,13 @@ class ThoughtSyncApplication : Application() {
|
||||
|
||||
// Introduce this app to any server it links to, before anything can sync.
|
||||
// The core cannot name us — the same crate is compiled into the desktop app,
|
||||
// and it used to announce every phone as `thoughtsync-desktop` carrying the
|
||||
// and it used to announce every phone as `inkwell-desktop` carrying the
|
||||
// core crate's own version. "unknown" rather than a guess when the package
|
||||
// manager will not say (note 3127 §5).
|
||||
setClientAgent("thoughtsync-android", installedVersionName() ?: "unknown")
|
||||
setClientAgent("inkwell-android", installedVersionName() ?: "unknown")
|
||||
|
||||
try {
|
||||
val handle = ThoughtSync(filesDir.absolutePath)
|
||||
val handle = Inkwell(filesDir.absolutePath)
|
||||
core = handle
|
||||
Log.i(TAG, "local store ready — ${handle.summary()}")
|
||||
} catch (e: Exception) {
|
||||
@@ -53,6 +53,6 @@ class ThoughtSyncApplication : Application() {
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val TAG = "ThoughtSync"
|
||||
const val TAG = "Inkwell"
|
||||
}
|
||||
}
|
||||
+21
-21
@@ -1,4 +1,4 @@
|
||||
package com.fabledsword.thoughtsync
|
||||
package com.fabledsword.inkwell
|
||||
|
||||
import android.Manifest
|
||||
import android.content.Intent
|
||||
@@ -22,22 +22,22 @@ import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import com.fabledsword.thoughtsync.core.ThoughtSync
|
||||
import com.fabledsword.thoughtsync.ui.BoardScreen
|
||||
import com.fabledsword.thoughtsync.ui.BoardSync
|
||||
import com.fabledsword.thoughtsync.ui.BoardUpdate
|
||||
import com.fabledsword.thoughtsync.ui.BoardViewModel
|
||||
import com.fabledsword.thoughtsync.ui.ForegroundTransitions
|
||||
import com.fabledsword.thoughtsync.ui.NoteEditorScreen
|
||||
import com.fabledsword.thoughtsync.ui.StoreUnavailableScreen
|
||||
import com.fabledsword.thoughtsync.ui.SyncScreen
|
||||
import com.fabledsword.thoughtsync.ui.SyncState
|
||||
import com.fabledsword.thoughtsync.ui.SyncViewModel
|
||||
import com.fabledsword.thoughtsync.ui.TagsScreen
|
||||
import com.fabledsword.thoughtsync.ui.TagsViewModel
|
||||
import com.fabledsword.thoughtsync.ui.ThoughtSyncTheme
|
||||
import com.fabledsword.thoughtsync.ui.UpdateViewModel
|
||||
import com.fabledsword.thoughtsync.ui.olderThan
|
||||
import com.fabledsword.inkwell.core.Inkwell
|
||||
import com.fabledsword.inkwell.ui.BoardScreen
|
||||
import com.fabledsword.inkwell.ui.BoardSync
|
||||
import com.fabledsword.inkwell.ui.BoardUpdate
|
||||
import com.fabledsword.inkwell.ui.BoardViewModel
|
||||
import com.fabledsword.inkwell.ui.ForegroundTransitions
|
||||
import com.fabledsword.inkwell.ui.InkwellTheme
|
||||
import com.fabledsword.inkwell.ui.NoteEditorScreen
|
||||
import com.fabledsword.inkwell.ui.StoreUnavailableScreen
|
||||
import com.fabledsword.inkwell.ui.SyncScreen
|
||||
import com.fabledsword.inkwell.ui.SyncState
|
||||
import com.fabledsword.inkwell.ui.SyncViewModel
|
||||
import com.fabledsword.inkwell.ui.TagsScreen
|
||||
import com.fabledsword.inkwell.ui.TagsViewModel
|
||||
import com.fabledsword.inkwell.ui.UpdateViewModel
|
||||
import com.fabledsword.inkwell.ui.olderThan
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
@@ -68,12 +68,12 @@ class MainActivity : ComponentActivity() {
|
||||
super.onCreate(savedInstanceState)
|
||||
enableEdgeToEdge()
|
||||
|
||||
val app = application as ThoughtSyncApplication
|
||||
val app = application as InkwellApplication
|
||||
requestedNote.value = takeRequestedNote(intent)
|
||||
sharedText.value = takeSharedText(intent)
|
||||
|
||||
setContent {
|
||||
ThoughtSyncTheme {
|
||||
InkwellTheme {
|
||||
val core = app.core
|
||||
if (core == null) {
|
||||
// The store never opened. There is no board to show and no
|
||||
@@ -174,7 +174,7 @@ private enum class Screen { BOARD, EDITOR, SYNC, TAGS }
|
||||
*/
|
||||
@Composable
|
||||
private fun App(
|
||||
core: ThoughtSync,
|
||||
core: Inkwell,
|
||||
requestedNote: MutableState<String?>,
|
||||
sharedText: MutableState<String?>,
|
||||
) {
|
||||
@@ -360,7 +360,7 @@ private fun App(
|
||||
* notifications this app would send — is spending it on nothing.
|
||||
*/
|
||||
@Composable
|
||||
private fun ReminderAlarms(core: ThoughtSync) {
|
||||
private fun ReminderAlarms(core: Inkwell) {
|
||||
val context = LocalContext.current
|
||||
val scope = rememberCoroutineScope()
|
||||
// Off the main thread: this reads every note that has a reminder, and a phone
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
package com.fabledsword.thoughtsync
|
||||
package com.fabledsword.inkwell
|
||||
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
@@ -8,7 +8,7 @@ import android.content.Intent
|
||||
import android.util.Log
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import com.fabledsword.thoughtsync.core.Note
|
||||
import com.fabledsword.inkwell.core.Note
|
||||
|
||||
/**
|
||||
* What a due reminder looks like in the shade.
|
||||
@@ -117,5 +117,5 @@ internal object ReminderNotification {
|
||||
)
|
||||
|
||||
private const val CHANNEL = "reminders"
|
||||
private const val TAG = "ThoughtSyncReminders"
|
||||
private const val TAG = "InkwellReminders"
|
||||
}
|
||||
+6
-6
@@ -1,4 +1,4 @@
|
||||
package com.fabledsword.thoughtsync
|
||||
package com.fabledsword.inkwell
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
@@ -36,7 +36,7 @@ class ReminderReceiver : BroadcastReceiver() {
|
||||
context: Context,
|
||||
intent: Intent,
|
||||
) {
|
||||
val core = (context.applicationContext as? ThoughtSyncApplication)?.core ?: return
|
||||
val core = (context.applicationContext as? InkwellApplication)?.core ?: return
|
||||
val action = intent.action
|
||||
val noteId = intent.getStringExtra(Reminders.EXTRA_NOTE_ID)
|
||||
val app = context.applicationContext
|
||||
@@ -64,9 +64,9 @@ class ReminderReceiver : BroadcastReceiver() {
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val ACTION_DUE = "com.fabledsword.thoughtsync.REMINDER_DUE"
|
||||
const val ACTION_DONE = "com.fabledsword.thoughtsync.REMINDER_DONE"
|
||||
const val ACTION_SNOOZE = "com.fabledsword.thoughtsync.REMINDER_SNOOZE"
|
||||
private const val TAG = "ThoughtSyncReminders"
|
||||
const val ACTION_DUE = "com.fabledsword.inkwell.REMINDER_DUE"
|
||||
const val ACTION_DONE = "com.fabledsword.inkwell.REMINDER_DONE"
|
||||
const val ACTION_SNOOZE = "com.fabledsword.inkwell.REMINDER_SNOOZE"
|
||||
private const val TAG = "InkwellReminders"
|
||||
}
|
||||
}
|
||||
+9
-9
@@ -1,4 +1,4 @@
|
||||
package com.fabledsword.thoughtsync
|
||||
package com.fabledsword.inkwell
|
||||
|
||||
import android.app.AlarmManager
|
||||
import android.app.PendingIntent
|
||||
@@ -7,8 +7,8 @@ import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.util.Log
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import com.fabledsword.thoughtsync.core.Note
|
||||
import com.fabledsword.thoughtsync.core.ThoughtSync
|
||||
import com.fabledsword.inkwell.core.Inkwell
|
||||
import com.fabledsword.inkwell.core.Note
|
||||
import java.time.OffsetDateTime
|
||||
|
||||
/**
|
||||
@@ -52,7 +52,7 @@ object Reminders {
|
||||
private const val MISSED_WINDOW_MS = 24L * 60 * 60 * 1000
|
||||
|
||||
private const val SNOOZE_MINUTES = 60L
|
||||
private const val TAG = "ThoughtSyncReminders"
|
||||
private const val TAG = "InkwellReminders"
|
||||
|
||||
/**
|
||||
* Announce what is due, then schedule the next one.
|
||||
@@ -63,7 +63,7 @@ object Reminders {
|
||||
*/
|
||||
fun refresh(
|
||||
context: Context,
|
||||
core: ThoughtSync,
|
||||
core: Inkwell,
|
||||
) {
|
||||
ReminderNotification.ensureChannel(context)
|
||||
val notes =
|
||||
@@ -111,7 +111,7 @@ object Reminders {
|
||||
*/
|
||||
fun promptToNotifyDue(
|
||||
context: Context,
|
||||
core: ThoughtSync,
|
||||
core: Inkwell,
|
||||
): Boolean =
|
||||
!Announced(context).askedToNotify &&
|
||||
!NotificationManagerCompat.from(context).areNotificationsEnabled() &&
|
||||
@@ -123,7 +123,7 @@ object Reminders {
|
||||
/** Clear the reminder, as the notification's Done action. */
|
||||
fun complete(
|
||||
context: Context,
|
||||
core: ThoughtSync,
|
||||
core: Inkwell,
|
||||
noteId: String,
|
||||
) {
|
||||
runCatching { core.completeReminder(noteId) }
|
||||
@@ -134,7 +134,7 @@ object Reminders {
|
||||
/** Push the reminder an hour out, as the notification's Snooze action. */
|
||||
fun snooze(
|
||||
context: Context,
|
||||
core: ThoughtSync,
|
||||
core: Inkwell,
|
||||
noteId: String,
|
||||
) {
|
||||
runCatching { core.snoozeReminder(noteId, SNOOZE_MINUTES) }
|
||||
@@ -237,7 +237,7 @@ private class Announced(
|
||||
fun markAsked() = prefs.edit().putBoolean(KEY_ASKED, true).apply()
|
||||
|
||||
private companion object {
|
||||
const val FILE = "thoughtsync-reminders"
|
||||
const val FILE = "inkwell-reminders"
|
||||
const val KEY_SEEN = "announced"
|
||||
const val KEY_PRIMED = "primed"
|
||||
const val KEY_ASKED = "asked_to_notify"
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
package com.fabledsword.thoughtsync
|
||||
package com.fabledsword.inkwell
|
||||
|
||||
import android.content.Context
|
||||
import androidx.work.BackoffPolicy
|
||||
@@ -85,8 +85,8 @@ object SyncSchedule {
|
||||
.setRequiredNetworkType(NetworkType.CONNECTED)
|
||||
.build()
|
||||
|
||||
private const val PERIODIC = "thoughtsync-periodic-sync"
|
||||
private const val PUSH = "thoughtsync-push-pending"
|
||||
private const val PERIODIC = "inkwell-periodic-sync"
|
||||
private const val PUSH = "inkwell-push-pending"
|
||||
|
||||
/** WorkManager's own minimum for periodic work. Asking for less gets this. */
|
||||
private const val PERIOD_MINUTES = 15L
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
package com.fabledsword.thoughtsync
|
||||
package com.fabledsword.inkwell
|
||||
|
||||
import android.content.Context
|
||||
|
||||
@@ -38,7 +38,7 @@ class SyncSettings(
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val FILE = "thoughtsync-sync"
|
||||
const val FILE = "inkwell-sync"
|
||||
const val KEY_AUTOMATIC = "automatic"
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -1,4 +1,4 @@
|
||||
package com.fabledsword.thoughtsync
|
||||
package com.fabledsword.inkwell
|
||||
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
@@ -8,7 +8,7 @@ import androidx.work.WorkerParameters
|
||||
/**
|
||||
* One sync cycle, run by the system rather than by a person.
|
||||
*
|
||||
* WorkManager may start the process to run this, which means [ThoughtSyncApplication.onCreate]
|
||||
* WorkManager may start the process to run this, which means [InkwellApplication.onCreate]
|
||||
* has already opened the store by the time [doWork] is called — the same handle
|
||||
* the UI uses, so there is never a second SQLite connection racing the first.
|
||||
*
|
||||
@@ -30,7 +30,7 @@ class SyncWorker(
|
||||
params: WorkerParameters,
|
||||
) : CoroutineWorker(context, params) {
|
||||
override suspend fun doWork(): Result {
|
||||
val core = (applicationContext as? ThoughtSyncApplication)?.core
|
||||
val core = (applicationContext as? InkwellApplication)?.core
|
||||
|
||||
// Both of these are "nothing to do", not "something went wrong", so both
|
||||
// report success and let the run retire quietly:
|
||||
@@ -67,6 +67,6 @@ class SyncWorker(
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val TAG = "ThoughtSyncWorker"
|
||||
const val TAG = "InkwellWorker"
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.fabledsword.thoughtsync
|
||||
package com.fabledsword.inkwell
|
||||
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
package com.fabledsword.thoughtsync
|
||||
package com.fabledsword.inkwell
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
@@ -71,7 +71,7 @@ class UpdateReceiver : BroadcastReceiver() {
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val ACTION_INSTALLED = "com.fabledsword.thoughtsync.UPDATE_INSTALLED"
|
||||
private const val TAG = "ThoughtSyncUpdate"
|
||||
const val ACTION_INSTALLED = "com.fabledsword.inkwell.UPDATE_INSTALLED"
|
||||
private const val TAG = "InkwellUpdate"
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
package com.fabledsword.thoughtsync.ui
|
||||
package com.fabledsword.inkwell.ui
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
@@ -33,7 +33,7 @@ import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.TextFieldValue
|
||||
import androidx.compose.ui.text.style.TextDecoration
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.fabledsword.thoughtsync.R
|
||||
import com.fabledsword.inkwell.R
|
||||
|
||||
/**
|
||||
* The note's body, as fields and checkboxes rather than as markup.
|
||||
+4
-4
@@ -1,4 +1,4 @@
|
||||
package com.fabledsword.thoughtsync.ui
|
||||
package com.fabledsword.inkwell.ui
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
@@ -63,9 +63,9 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.fabledsword.thoughtsync.R
|
||||
import com.fabledsword.thoughtsync.core.Label
|
||||
import com.fabledsword.thoughtsync.core.Note
|
||||
import com.fabledsword.inkwell.R
|
||||
import com.fabledsword.inkwell.core.Label
|
||||
import com.fabledsword.inkwell.core.Note
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@Composable
|
||||
+10
-10
@@ -1,4 +1,4 @@
|
||||
package com.fabledsword.thoughtsync.ui
|
||||
package com.fabledsword.inkwell.ui
|
||||
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
@@ -6,12 +6,12 @@ import androidx.compose.runtime.setValue
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.fabledsword.thoughtsync.core.Label
|
||||
import com.fabledsword.thoughtsync.core.Note
|
||||
import com.fabledsword.thoughtsync.core.NoteDraft
|
||||
import com.fabledsword.thoughtsync.core.NoteEdit
|
||||
import com.fabledsword.thoughtsync.core.NoteQuery
|
||||
import com.fabledsword.thoughtsync.core.ThoughtSync
|
||||
import com.fabledsword.inkwell.core.Inkwell
|
||||
import com.fabledsword.inkwell.core.Label
|
||||
import com.fabledsword.inkwell.core.Note
|
||||
import com.fabledsword.inkwell.core.NoteDraft
|
||||
import com.fabledsword.inkwell.core.NoteEdit
|
||||
import com.fabledsword.inkwell.core.NoteQuery
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.delay
|
||||
@@ -99,7 +99,7 @@ data class BoardState(
|
||||
*/
|
||||
@Suppress("TooManyFunctions")
|
||||
class BoardViewModel(
|
||||
private val core: ThoughtSync,
|
||||
private val core: Inkwell,
|
||||
/**
|
||||
* Called after any write that could have moved a reminder.
|
||||
*
|
||||
@@ -482,7 +482,7 @@ class BoardViewModel(
|
||||
*/
|
||||
private fun mutate(
|
||||
closeEditor: Boolean = false,
|
||||
block: (ThoughtSync) -> Note?,
|
||||
block: (Inkwell) -> Note?,
|
||||
) {
|
||||
viewModelScope.launch {
|
||||
state = state.copy(saving = true)
|
||||
@@ -547,7 +547,7 @@ class BoardViewModel(
|
||||
private const val VIEW_TRASH = "trash"
|
||||
|
||||
fun factory(
|
||||
core: ThoughtSync,
|
||||
core: Inkwell,
|
||||
onRemindersChanged: () -> Unit,
|
||||
): ViewModelProvider.Factory =
|
||||
object : ViewModelProvider.Factory {
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.fabledsword.thoughtsync.ui
|
||||
package com.fabledsword.inkwell.ui
|
||||
|
||||
// The colour a LABEL wears when nobody picked one for it.
|
||||
//
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.fabledsword.thoughtsync.ui
|
||||
package com.fabledsword.inkwell.ui
|
||||
|
||||
/**
|
||||
* Everything the editor can ask for, as one type.
|
||||
+3
-3
@@ -1,10 +1,10 @@
|
||||
package com.fabledsword.thoughtsync.ui
|
||||
package com.fabledsword.inkwell.ui
|
||||
|
||||
import androidx.compose.runtime.saveable.Saver
|
||||
import androidx.compose.ui.text.TextRange
|
||||
import androidx.compose.ui.text.input.TextFieldValue
|
||||
import com.fabledsword.thoughtsync.core.checklistItems
|
||||
import com.fabledsword.thoughtsync.core.checklistRender
|
||||
import com.fabledsword.inkwell.core.checklistItems
|
||||
import com.fabledsword.inkwell.core.checklistRender
|
||||
|
||||
/**
|
||||
* One piece of a note body, as the editor DRAWS it.
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
package com.fabledsword.thoughtsync.ui
|
||||
package com.fabledsword.inkwell.ui
|
||||
|
||||
import android.text.format.DateUtils
|
||||
import androidx.compose.foundation.background
|
||||
@@ -41,8 +41,8 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.fabledsword.thoughtsync.R
|
||||
import com.fabledsword.thoughtsync.core.Note
|
||||
import com.fabledsword.inkwell.R
|
||||
import com.fabledsword.inkwell.core.Note
|
||||
|
||||
/**
|
||||
* The editor's action bar, along the top of the surface.
|
||||
+4
-4
@@ -1,4 +1,4 @@
|
||||
package com.fabledsword.thoughtsync.ui
|
||||
package com.fabledsword.inkwell.ui
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
@@ -36,9 +36,9 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.fabledsword.thoughtsync.R
|
||||
import com.fabledsword.thoughtsync.core.Label
|
||||
import com.fabledsword.thoughtsync.core.Note
|
||||
import com.fabledsword.inkwell.R
|
||||
import com.fabledsword.inkwell.core.Label
|
||||
import com.fabledsword.inkwell.core.Note
|
||||
import java.time.DayOfWeek
|
||||
import java.time.Instant
|
||||
import java.time.LocalDate
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
package com.fabledsword.thoughtsync.ui
|
||||
package com.fabledsword.inkwell.ui
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.border
|
||||
@@ -16,7 +16,7 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.fabledsword.thoughtsync.R
|
||||
import com.fabledsword.inkwell.R
|
||||
|
||||
// Shared by the board and the editor.
|
||||
//
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.fabledsword.thoughtsync.ui
|
||||
package com.fabledsword.inkwell.ui
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.fabledsword.thoughtsync.ui
|
||||
package com.fabledsword.inkwell.ui
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
package com.fabledsword.thoughtsync.ui
|
||||
package com.fabledsword.inkwell.ui
|
||||
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.layout.Column
|
||||
@@ -12,8 +12,8 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.fabledsword.thoughtsync.core.LinkPreview
|
||||
import com.fabledsword.thoughtsync.core.Note
|
||||
import com.fabledsword.inkwell.core.LinkPreview
|
||||
import com.fabledsword.inkwell.core.Note
|
||||
|
||||
private val PREVIEW_RADIUS = 8.dp
|
||||
|
||||
+7
-7
@@ -1,4 +1,4 @@
|
||||
package com.fabledsword.thoughtsync.ui
|
||||
package com.fabledsword.inkwell.ui
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.border
|
||||
@@ -38,12 +38,12 @@ import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextDecoration
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.fabledsword.thoughtsync.R
|
||||
import com.fabledsword.thoughtsync.core.BodyItem
|
||||
import com.fabledsword.thoughtsync.core.Note
|
||||
import com.fabledsword.thoughtsync.core.NoteLabel
|
||||
import com.fabledsword.thoughtsync.core.bodyTags
|
||||
import com.fabledsword.thoughtsync.core.checklistItems
|
||||
import com.fabledsword.inkwell.R
|
||||
import com.fabledsword.inkwell.core.BodyItem
|
||||
import com.fabledsword.inkwell.core.Note
|
||||
import com.fabledsword.inkwell.core.NoteLabel
|
||||
import com.fabledsword.inkwell.core.bodyTags
|
||||
import com.fabledsword.inkwell.core.checklistItems
|
||||
|
||||
@Composable
|
||||
fun NoteCard(
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
package com.fabledsword.thoughtsync.ui
|
||||
package com.fabledsword.inkwell.ui
|
||||
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
@@ -25,8 +25,8 @@ import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.fabledsword.thoughtsync.core.Label
|
||||
import com.fabledsword.thoughtsync.core.Note
|
||||
import com.fabledsword.inkwell.core.Label
|
||||
import com.fabledsword.inkwell.core.Note
|
||||
import kotlinx.coroutines.delay
|
||||
|
||||
/**
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.fabledsword.thoughtsync.ui
|
||||
package com.fabledsword.inkwell.ui
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.ReadOnlyComposable
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
package com.fabledsword.thoughtsync.ui
|
||||
package com.fabledsword.inkwell.ui
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.foundation.background
|
||||
@@ -20,7 +20,7 @@ import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.fabledsword.thoughtsync.R
|
||||
import com.fabledsword.inkwell.R
|
||||
|
||||
/**
|
||||
* A bordered block, tinted from the same table the notes use.
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.fabledsword.thoughtsync.ui
|
||||
package com.fabledsword.inkwell.ui
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
package com.fabledsword.thoughtsync.ui
|
||||
package com.fabledsword.inkwell.ui
|
||||
|
||||
import android.app.AlarmManager
|
||||
import android.content.Context
|
||||
@@ -17,8 +17,8 @@ import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import com.fabledsword.thoughtsync.R
|
||||
import com.fabledsword.thoughtsync.Reminders
|
||||
import com.fabledsword.inkwell.R
|
||||
import com.fabledsword.inkwell.Reminders
|
||||
|
||||
/**
|
||||
* Says so when a reminder would not actually reach anyone.
|
||||
+4
-4
@@ -1,4 +1,4 @@
|
||||
package com.fabledsword.thoughtsync.ui
|
||||
package com.fabledsword.inkwell.ui
|
||||
|
||||
import android.os.Build
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
@@ -27,9 +27,9 @@ import androidx.compose.ui.text.input.KeyboardCapitalization
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.text.input.PasswordVisualTransformation
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.fabledsword.thoughtsync.R
|
||||
import com.fabledsword.thoughtsync.core.Compatibility
|
||||
import com.fabledsword.thoughtsync.core.RevokeOutcome
|
||||
import com.fabledsword.inkwell.R
|
||||
import com.fabledsword.inkwell.core.Compatibility
|
||||
import com.fabledsword.inkwell.core.RevokeOutcome
|
||||
|
||||
// Becoming linked: the probe-then-sign-in flow, and the notices around it.
|
||||
//
|
||||
+5
-5
@@ -1,4 +1,4 @@
|
||||
package com.fabledsword.thoughtsync.ui
|
||||
package com.fabledsword.inkwell.ui
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
@@ -36,15 +36,15 @@ import androidx.compose.ui.res.pluralStringResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.fabledsword.thoughtsync.R
|
||||
import com.fabledsword.thoughtsync.UpdateOutcome
|
||||
import com.fabledsword.thoughtsync.installedVersionName
|
||||
import com.fabledsword.inkwell.R
|
||||
import com.fabledsword.inkwell.UpdateOutcome
|
||||
import com.fabledsword.inkwell.installedVersionName
|
||||
|
||||
/**
|
||||
* Opt-in server pairing.
|
||||
*
|
||||
* The whole screen is written around one idea: **being unlinked is not a
|
||||
* problem.** ThoughtSync is local-first and completely usable having never opened
|
||||
* problem.** Inkwell is local-first and completely usable having never opened
|
||||
* this screen, so the unlinked state leads with "Working offline on this device"
|
||||
* and explains what connecting would ADD, rather than presenting an empty form as
|
||||
* unfinished setup.
|
||||
+4
-4
@@ -1,11 +1,11 @@
|
||||
package com.fabledsword.thoughtsync.ui
|
||||
package com.fabledsword.inkwell.ui
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.res.pluralStringResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import com.fabledsword.thoughtsync.R
|
||||
import com.fabledsword.thoughtsync.core.Compatibility
|
||||
import com.fabledsword.thoughtsync.core.SyncOutcome
|
||||
import com.fabledsword.inkwell.R
|
||||
import com.fabledsword.inkwell.core.Compatibility
|
||||
import com.fabledsword.inkwell.core.SyncOutcome
|
||||
|
||||
// Turning sync results into sentences.
|
||||
//
|
||||
+9
-9
@@ -1,4 +1,4 @@
|
||||
package com.fabledsword.thoughtsync.ui
|
||||
package com.fabledsword.inkwell.ui
|
||||
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
@@ -6,12 +6,12 @@ import androidx.compose.runtime.setValue
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.fabledsword.thoughtsync.core.Compatibility
|
||||
import com.fabledsword.thoughtsync.core.ProbeResult
|
||||
import com.fabledsword.thoughtsync.core.RevokeOutcome
|
||||
import com.fabledsword.thoughtsync.core.SyncOutcome
|
||||
import com.fabledsword.thoughtsync.core.SyncStatus
|
||||
import com.fabledsword.thoughtsync.core.ThoughtSync
|
||||
import com.fabledsword.inkwell.core.Compatibility
|
||||
import com.fabledsword.inkwell.core.Inkwell
|
||||
import com.fabledsword.inkwell.core.ProbeResult
|
||||
import com.fabledsword.inkwell.core.RevokeOutcome
|
||||
import com.fabledsword.inkwell.core.SyncOutcome
|
||||
import com.fabledsword.inkwell.core.SyncStatus
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
@@ -113,7 +113,7 @@ data class SyncState(
|
||||
* stored cursor next time (Scribe #2736).
|
||||
*/
|
||||
class SyncViewModel(
|
||||
private val core: ThoughtSync,
|
||||
private val core: Inkwell,
|
||||
/**
|
||||
* Called after a sync that changed the store.
|
||||
*
|
||||
@@ -316,7 +316,7 @@ class SyncViewModel(
|
||||
|
||||
companion object {
|
||||
fun factory(
|
||||
core: ThoughtSync,
|
||||
core: Inkwell,
|
||||
onStoreChanged: () -> Unit,
|
||||
): ViewModelProvider.Factory =
|
||||
object : ViewModelProvider.Factory {
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
package com.fabledsword.thoughtsync.ui
|
||||
package com.fabledsword.inkwell.ui
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.border
|
||||
@@ -43,8 +43,8 @@ import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.fabledsword.thoughtsync.R
|
||||
import com.fabledsword.thoughtsync.core.Label
|
||||
import com.fabledsword.inkwell.R
|
||||
import com.fabledsword.inkwell.core.Label
|
||||
|
||||
/** The swatch shown beside a tag, and tapped to change its colour. */
|
||||
private val SWATCH = 22.dp
|
||||
+6
-6
@@ -1,4 +1,4 @@
|
||||
package com.fabledsword.thoughtsync.ui
|
||||
package com.fabledsword.inkwell.ui
|
||||
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
@@ -6,8 +6,8 @@ import androidx.compose.runtime.setValue
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.fabledsword.thoughtsync.core.Label
|
||||
import com.fabledsword.thoughtsync.core.ThoughtSync
|
||||
import com.fabledsword.inkwell.core.Inkwell
|
||||
import com.fabledsword.inkwell.core.Label
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
@@ -57,7 +57,7 @@ data class TagsState(
|
||||
* the core marks the rows dirty and the next sync carries them.
|
||||
*/
|
||||
class TagsViewModel(
|
||||
private val core: ThoughtSync,
|
||||
private val core: Inkwell,
|
||||
/**
|
||||
* Called after any write that landed.
|
||||
*
|
||||
@@ -140,7 +140,7 @@ class TagsViewModel(
|
||||
* `busy` is cleared in the same assignment that stores the result, so no path
|
||||
* out of here can leave the screen stuck with its controls disabled.
|
||||
*/
|
||||
private fun write(block: (ThoughtSync) -> Unit) {
|
||||
private fun write(block: (Inkwell) -> Unit) {
|
||||
if (state.busy) return
|
||||
state = state.copy(busy = true, error = null)
|
||||
viewModelScope.launch {
|
||||
@@ -164,7 +164,7 @@ class TagsViewModel(
|
||||
|
||||
companion object {
|
||||
fun factory(
|
||||
core: ThoughtSync,
|
||||
core: Inkwell,
|
||||
onStoreChanged: () -> Unit,
|
||||
): ViewModelProvider.Factory =
|
||||
object : ViewModelProvider.Factory {
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
package com.fabledsword.thoughtsync.ui
|
||||
package com.fabledsword.inkwell.ui
|
||||
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
@@ -59,7 +59,7 @@ private val DarkColors =
|
||||
)
|
||||
|
||||
/**
|
||||
* Material 3 in ThoughtSync's own colours, following the system light/dark setting.
|
||||
* Material 3 in Inkwell's own colours, following the system light/dark setting.
|
||||
*
|
||||
* DELIBERATELY NOT Material You dynamic colour, which this used until the operator
|
||||
* saw the first build. Dynamic colour is the more Android-native choice and it
|
||||
@@ -72,7 +72,7 @@ private val DarkColors =
|
||||
* If dynamic colour is ever wanted it belongs behind a setting, not as the default.
|
||||
*/
|
||||
@Composable
|
||||
fun ThoughtSyncTheme(
|
||||
fun InkwellTheme(
|
||||
darkTheme: Boolean = isSystemInDarkTheme(),
|
||||
content: @Composable () -> Unit,
|
||||
) {
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.fabledsword.thoughtsync.ui
|
||||
package com.fabledsword.inkwell.ui
|
||||
|
||||
import java.time.LocalDateTime
|
||||
import java.time.OffsetDateTime
|
||||
+4
-4
@@ -1,4 +1,4 @@
|
||||
package com.fabledsword.thoughtsync.ui
|
||||
package com.fabledsword.inkwell.ui
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.border
|
||||
@@ -25,9 +25,9 @@ import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.fabledsword.thoughtsync.AppUpdate
|
||||
import com.fabledsword.thoughtsync.R
|
||||
import com.fabledsword.thoughtsync.UpdateOutcome
|
||||
import com.fabledsword.inkwell.AppUpdate
|
||||
import com.fabledsword.inkwell.R
|
||||
import com.fabledsword.inkwell.UpdateOutcome
|
||||
|
||||
/**
|
||||
* Updating the app from the server it is linked to.
|
||||
+7
-7
@@ -1,4 +1,4 @@
|
||||
package com.fabledsword.thoughtsync.ui
|
||||
package com.fabledsword.inkwell.ui
|
||||
|
||||
import android.content.Context
|
||||
import androidx.compose.runtime.getValue
|
||||
@@ -7,10 +7,10 @@ import androidx.compose.runtime.setValue
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.fabledsword.thoughtsync.AppUpdate
|
||||
import com.fabledsword.thoughtsync.UpdateOutcome
|
||||
import com.fabledsword.thoughtsync.core.ClientUpdate
|
||||
import com.fabledsword.thoughtsync.core.ThoughtSync
|
||||
import com.fabledsword.inkwell.AppUpdate
|
||||
import com.fabledsword.inkwell.UpdateOutcome
|
||||
import com.fabledsword.inkwell.core.ClientUpdate
|
||||
import com.fabledsword.inkwell.core.Inkwell
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
@@ -61,7 +61,7 @@ data class UpdateState(
|
||||
* secret this app holds across two languages for no gain.
|
||||
*/
|
||||
class UpdateViewModel(
|
||||
private val core: ThoughtSync,
|
||||
private val core: Inkwell,
|
||||
/**
|
||||
* MUST be the application context — it outlives this view model, and holding an
|
||||
* Activity here is the textbook way to leak a window.
|
||||
@@ -207,7 +207,7 @@ class UpdateViewModel(
|
||||
|
||||
companion object {
|
||||
fun factory(
|
||||
core: ThoughtSync,
|
||||
core: Inkwell,
|
||||
context: Context,
|
||||
): ViewModelProvider.Factory =
|
||||
object : ViewModelProvider.Factory {
|
||||
@@ -2,6 +2,6 @@
|
||||
<resources>
|
||||
<!-- The product's brand colour, same value the web app's manifest and
|
||||
<meta name="theme-color"> already use. One source of truth for "what
|
||||
colour is ThoughtSync" across the three surfaces. -->
|
||||
colour is Inkwell" across the three surfaces. -->
|
||||
<color name="ic_launcher_background">#F5C518</color>
|
||||
</resources>
|
||||
|
||||
@@ -6,5 +6,5 @@
|
||||
truth in XML — the same reason the desktop reads its live theme rather
|
||||
than hardcoding a window colour.
|
||||
-->
|
||||
<style name="Theme.ThoughtSync" parent="android:Theme.Material.NoActionBar" />
|
||||
<style name="Theme.Inkwell" parent="android:Theme.Material.NoActionBar" />
|
||||
</resources>
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.fabledsword.thoughtsync.ui
|
||||
package com.fabledsword.inkwell.ui
|
||||
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertNotEquals
|
||||
@@ -74,7 +74,7 @@ exceptions:
|
||||
# right and still applies.
|
||||
excludes:
|
||||
- "**/ui/**"
|
||||
- "**/ThoughtSyncApplication.kt"
|
||||
- "**/InkwellApplication.kt"
|
||||
- "**/SyncWorker.kt"
|
||||
- "**/ReminderReceiver.kt"
|
||||
- "**/AppUpdate.kt"
|
||||
|
||||
+19
-19
@@ -7,7 +7,7 @@
|
||||
//!
|
||||
//! ## Shape
|
||||
//!
|
||||
//! One `ThoughtSync` object holds the store and the blob directory, mirroring how
|
||||
//! One `Inkwell` object holds the store and the blob directory, mirroring how
|
||||
//! Tauri manages them as app state. Kotlin constructs it once, keeps it for the
|
||||
//! process lifetime, and calls methods on it.
|
||||
//!
|
||||
@@ -108,13 +108,13 @@ impl CoreError {
|
||||
/// behind its mutex, the blob store being a path — which is what lets uniffi share
|
||||
/// one instance across coroutines.
|
||||
#[derive(uniffi::Object)]
|
||||
pub struct ThoughtSync {
|
||||
pub struct Inkwell {
|
||||
db: Db,
|
||||
blobs: BlobStore,
|
||||
}
|
||||
|
||||
#[uniffi::export]
|
||||
impl ThoughtSync {
|
||||
impl Inkwell {
|
||||
/// Open (creating on first run) the store under `data_dir`, and the attachment
|
||||
/// directory beside it.
|
||||
///
|
||||
@@ -131,7 +131,7 @@ impl ThoughtSync {
|
||||
log::info!("local store ready — {}", local::summary(&db));
|
||||
|
||||
let blobs = BlobStore::new(dir.join("blobs")).map_err(CoreError::store)?;
|
||||
Ok(Arc::new(ThoughtSync { db, blobs }))
|
||||
Ok(Arc::new(Inkwell { db, blobs }))
|
||||
}
|
||||
|
||||
/// A one-line count summary, for the boot log.
|
||||
@@ -413,7 +413,7 @@ impl ThoughtSync {
|
||||
/// functions. Split into its own impl block so the runtime attribute — and the fact
|
||||
/// that everything in here touches the network — is visible at a glance.
|
||||
#[uniffi::export(async_runtime = "tokio")]
|
||||
impl ThoughtSync {
|
||||
impl Inkwell {
|
||||
/// Ask a server who it is, without committing to anything. Called as the user
|
||||
/// finishes typing an address, so they see what answered before handing over
|
||||
/// credentials.
|
||||
@@ -525,7 +525,7 @@ impl ThoughtSync {
|
||||
///
|
||||
/// Takes the destination rather than choosing one: only Android knows a
|
||||
/// directory its own package installer can read from, and the core has no
|
||||
/// business guessing at platform paths — the same reason `ThoughtSync::new`
|
||||
/// business guessing at platform paths — the same reason `Inkwell::new`
|
||||
/// takes a data dir.
|
||||
pub async fn download_client_update(&self, dest_path: String) -> Result<(), CoreError> {
|
||||
let (base_url, token) = self.credentials()?;
|
||||
@@ -587,7 +587,7 @@ pub fn checklist_render(text: String, checked: bool) -> String {
|
||||
/// stamps and nobody has seen. The honest value is the installed package's own
|
||||
/// `versionName`, which is what Kotlin passes here.
|
||||
///
|
||||
/// Called once from `ThoughtSyncApplication.onCreate`, before anything can sync.
|
||||
/// Called once from `InkwellApplication.onCreate`, before anything can sync.
|
||||
#[uniffi::export]
|
||||
pub fn set_client_agent(name: String, version: String) {
|
||||
compat::set_client_agent(&name, &version);
|
||||
@@ -620,7 +620,7 @@ pub fn body_tags(body: String) -> Vec<BodyTag> {
|
||||
|
||||
/// Helpers, deliberately NOT exported — uniffi only binds what an `#[uniffi::export]`
|
||||
/// block names, so these stay Rust-side.
|
||||
impl ThoughtSync {
|
||||
impl Inkwell {
|
||||
/// Apply a `{text}` or `{checked}` patch to one checklist item.
|
||||
///
|
||||
/// The two public setters differ only in the key they write, and the lock +
|
||||
@@ -701,7 +701,7 @@ mod tests {
|
||||
#[test]
|
||||
fn creates_a_store_and_round_trips_a_note() {
|
||||
let dir = scratch_dir();
|
||||
let app = ThoughtSync::new(dir.clone()).expect("a fresh data dir should open");
|
||||
let app = Inkwell::new(dir.clone()).expect("a fresh data dir should open");
|
||||
|
||||
let created = app
|
||||
.create_note(draft("Groceries\nmilk"))
|
||||
@@ -723,7 +723,7 @@ mod tests {
|
||||
#[test]
|
||||
fn a_note_is_named_by_its_first_line() {
|
||||
let dir = scratch_dir();
|
||||
let app = ThoughtSync::new(dir.clone()).expect("a fresh data dir should open");
|
||||
let app = Inkwell::new(dir.clone()).expect("a fresh data dir should open");
|
||||
|
||||
let created = app
|
||||
.create_note(draft("just a thought"))
|
||||
@@ -738,7 +738,7 @@ mod tests {
|
||||
#[test]
|
||||
fn a_note_with_only_items_is_named_by_its_first_item() {
|
||||
let dir = scratch_dir();
|
||||
let app = ThoughtSync::new(dir.clone()).expect("a fresh data dir should open");
|
||||
let app = Inkwell::new(dir.clone()).expect("a fresh data dir should open");
|
||||
|
||||
let created = app
|
||||
.create_note(NoteDraft {
|
||||
@@ -757,7 +757,7 @@ mod tests {
|
||||
#[test]
|
||||
fn syncing_unlinked_reports_not_linked() {
|
||||
let dir = scratch_dir();
|
||||
let app = ThoughtSync::new(dir.clone()).expect("a fresh data dir should open");
|
||||
let app = Inkwell::new(dir.clone()).expect("a fresh data dir should open");
|
||||
|
||||
let status = app.sync_status().expect("status should read");
|
||||
assert!(!status.linked);
|
||||
@@ -774,7 +774,7 @@ mod tests {
|
||||
#[test]
|
||||
fn checklist_items_can_be_added_ticked_retitled_and_removed() {
|
||||
let dir = scratch_dir();
|
||||
let app = ThoughtSync::new(dir.clone()).expect("a fresh data dir should open");
|
||||
let app = Inkwell::new(dir.clone()).expect("a fresh data dir should open");
|
||||
let note = app
|
||||
.create_note(NoteDraft {
|
||||
body: "Packing".to_string(),
|
||||
@@ -828,7 +828,7 @@ mod tests {
|
||||
#[test]
|
||||
fn setting_labels_leaves_tag_derived_ones_alone() {
|
||||
let dir = scratch_dir();
|
||||
let app = ThoughtSync::new(dir.clone()).expect("a fresh data dir should open");
|
||||
let app = Inkwell::new(dir.clone()).expect("a fresh data dir should open");
|
||||
|
||||
let note = app
|
||||
.create_note(draft("Trip\nbook the ferry #travel"))
|
||||
@@ -869,7 +869,7 @@ mod tests {
|
||||
#[test]
|
||||
fn deleting_forever_removes_the_note() {
|
||||
let dir = scratch_dir();
|
||||
let app = ThoughtSync::new(dir.clone()).expect("a fresh data dir should open");
|
||||
let app = Inkwell::new(dir.clone()).expect("a fresh data dir should open");
|
||||
let note = app.create_note(draft("Ephemeral\nbody")).expect("create");
|
||||
|
||||
app.delete_note_forever(note.id.clone())
|
||||
@@ -886,7 +886,7 @@ mod tests {
|
||||
#[test]
|
||||
fn reminders_can_be_snoozed_and_completed() {
|
||||
let dir = scratch_dir();
|
||||
let app = ThoughtSync::new(dir.clone()).expect("a fresh data dir should open");
|
||||
let app = Inkwell::new(dir.clone()).expect("a fresh data dir should open");
|
||||
let note = app.create_note(draft("Call back")).expect("create");
|
||||
assert_eq!(note.remind_at, None);
|
||||
|
||||
@@ -912,7 +912,7 @@ mod tests {
|
||||
#[test]
|
||||
fn completing_a_recurring_reminder_moves_it_rather_than_ending_it() {
|
||||
let dir = scratch_dir();
|
||||
let app = ThoughtSync::new(dir.clone()).expect("a fresh data dir should open");
|
||||
let app = Inkwell::new(dir.clone()).expect("a fresh data dir should open");
|
||||
let note = app.create_note(draft("Water the plants")).expect("create");
|
||||
|
||||
let armed = app
|
||||
@@ -974,7 +974,7 @@ mod tests {
|
||||
#[test]
|
||||
fn renaming_onto_an_existing_tag_merges_into_the_older_one() {
|
||||
let dir = scratch_dir();
|
||||
let app = ThoughtSync::new(dir.clone()).expect("a fresh data dir should open");
|
||||
let app = Inkwell::new(dir.clone()).expect("a fresh data dir should open");
|
||||
|
||||
let older = app.create_label("grocery".to_string()).expect("older");
|
||||
// `created_at` is RFC3339 to the MILLISECOND. Without a gap the two rows can
|
||||
@@ -1019,7 +1019,7 @@ mod tests {
|
||||
#[test]
|
||||
fn the_rename_merge_survivor_does_not_depend_on_the_direction() {
|
||||
let dir = scratch_dir();
|
||||
let app = ThoughtSync::new(dir.clone()).expect("a fresh data dir should open");
|
||||
let app = Inkwell::new(dir.clone()).expect("a fresh data dir should open");
|
||||
|
||||
let older = app.create_label("grocery".to_string()).expect("older");
|
||||
std::thread::sleep(std::time::Duration::from_millis(5));
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Where the generated Kotlin lands. Matches the app's package so the bindings are
|
||||
# `com.fabledsword.thoughtsync.core.*` rather than something the app has to alias.
|
||||
# `com.fabledsword.inkwell.core.*` rather than something the app has to alias.
|
||||
[bindings.kotlin]
|
||||
package_name = "com.fabledsword.thoughtsync.core"
|
||||
package_name = "com.fabledsword.inkwell.core"
|
||||
cdylib_name = "inkwell_ffi"
|
||||
|
||||
@@ -18,7 +18,7 @@ dependencyResolutionManagement {
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
rootProject.name = "ThoughtSync"
|
||||
rootProject.name = "Inkwell"
|
||||
|
||||
// `ffi/` sits beside `app/` but is deliberately NOT a Gradle module: it is a Rust
|
||||
// crate belonging to the Cargo workspace at the repo root. Gradle reaches it by
|
||||
|
||||
@@ -72,8 +72,8 @@ ASSETS=(
|
||||
"$BUNDLE_ROOT"/arch/*.pkg.tar.*
|
||||
"$WIN_BUNDLE_ROOT"/nsis/*.exe
|
||||
"$WIN_BUNDLE_ROOT"/nsis/*.exe.sig
|
||||
"$REPO_ROOT"/android/dist/thoughtsync.apk
|
||||
"$REPO_ROOT"/android/dist/thoughtsync-android.json
|
||||
"$REPO_ROOT"/android/dist/inkwell.apk
|
||||
"$REPO_ROOT"/android/dist/inkwell-android.json
|
||||
)
|
||||
# nullglob drops PATTERNS that match nothing — it does nothing for a path with no
|
||||
# wildcard in it, which stays in the array as a literal and reaches curl as a file
|
||||
|
||||
@@ -229,7 +229,7 @@ if [ "${PRUNE_OLD_ASSETS:-false}" = "true" ]; then
|
||||
# every desktop push regardless. That is exactly what happened on run
|
||||
# 4098, which swept the APK run 4092 had just published.
|
||||
case "$asset_name" in
|
||||
latest.json|inkwell-desktop.json|thoughtsync.apk|thoughtsync-android.json) continue ;;
|
||||
latest.json|inkwell-desktop.json|inkwell.apk|inkwell-android.json) continue ;;
|
||||
*"$APP_VERSION"*) continue ;;
|
||||
esac
|
||||
echo " removing $asset_name"
|
||||
|
||||
@@ -88,8 +88,8 @@ echo "==> Collecting the $channel clients"
|
||||
# Its sidecar is published whole by the Android lane — an APK keeps its version in
|
||||
# a binary AXML manifest, so the values are recorded where they were already known.
|
||||
# Copied verbatim rather than rebuilt here.
|
||||
if fetch "$BASE/thoughtsync.apk" "$dest/inkwell.apk" &&
|
||||
fetch "$BASE/thoughtsync-android.json" "$dest/inkwell-android.json"; then
|
||||
if fetch "$BASE/inkwell.apk" "$dest/inkwell.apk" &&
|
||||
fetch "$BASE/inkwell-android.json" "$dest/inkwell-android.json"; then
|
||||
echo " android $(field "$dest/inkwell-android.json" version_name)"
|
||||
else
|
||||
# Both or neither. Half a pair is worse than none: the server would read a
|
||||
|
||||
@@ -110,7 +110,7 @@ published_for() {
|
||||
| sed -E 's/.*"([^"]+)"$/\1/'; } || true
|
||||
;;
|
||||
android)
|
||||
{ fetch "$SERVER/$REPO/releases/download/$_tag/thoughtsync-android.json" \
|
||||
{ fetch "$SERVER/$REPO/releases/download/$_tag/inkwell-android.json" \
|
||||
| grep -oE '"version_code"[[:space:]]*:[[:space:]]*[0-9]+' | head -1 \
|
||||
| grep -oE '[0-9]+$'; } || true
|
||||
;;
|
||||
@@ -126,7 +126,7 @@ published_name() {
|
||||
case "$1" in
|
||||
desktop) published_for desktop "$2" ;;
|
||||
android)
|
||||
{ fetch "$SERVER/$REPO/releases/download/$_tag/thoughtsync-android.json" \
|
||||
{ fetch "$SERVER/$REPO/releases/download/$_tag/inkwell-android.json" \
|
||||
| grep -oE '"version_name"[[:space:]]*:[[:space:]]*"[^"]+"' | head -1 \
|
||||
| sed -E 's/.*"([^"]+)"$/\1/'; } || true
|
||||
;;
|
||||
|
||||
Reference in New Issue
Block a user