conduit/lib/features/release_notes/release_notes_bootstrap.dart
cogwheel 677a20e2ba
Redesign the Conduit 4.0 release announcement (#602)
* feat: bundled JSON release notes for 4.0, polished changelog sheet, remove IAP

- Move release-note content from ARB to assets/release_notes/<locale>.json
  with locale-fallback repository and schema-checked validator
- Polish the release notes sheet (staggered reveal, version badge,
  feature glyph bullets, action cards) and add the 4.0 note in 13 locales
- Prune pre-4.0 notes
- Remove in_app_purchase and the tip jar entirely; keep the Buy Me a
  Coffee donation link on all platforms

* Refresh release notes sheet and localized copy

* Add release notes banner and native review support

* Redesign release announcement sheet

* Target release announcement to 4.0.1

* Address release announcement review feedback

* Tighten release note locale handling
2026-07-31 21:54:47 +05:30

57 lines
2.1 KiB
Dart

import '../../core/persistence/persistence_keys.dart';
import '../../core/persistence/preferences_store.dart';
/// Last public version before automatic release notes first ship in 4.0.1.
///
/// Existing installs have no release-note version marker yet, so this baseline
/// lets the normal semantic-version gate select the bundled 4.0.1 note without
/// making a fresh 4.0.1 install look like an update.
const releaseNotesLegacyBaselineVersion = '3.4.3';
/// Captures install provenance before onboarding can create the same markers.
///
/// This must run once, after legacy preferences have migrated and before
/// [runApp]. An install with no existing configuration is considered fresh;
/// installs with an Open WebUI server or an accountless backend are upgrades.
Future<void> captureReleaseNotesInstallProvenance() async {
if (PreferencesStore.containsKey(
PreferenceKeys.releaseNotesExistingInstallAtBootstrap,
) ||
PreferencesStore.containsKey(PreferenceKeys.lastSeenReleaseVersion)) {
return;
}
await PreferencesStore.put(
PreferenceKeys.releaseNotesExistingInstallAtBootstrap,
_hasExistingConfiguration(),
);
}
String? releaseNotesPreviousVersionForEvaluation(String? lastSeenVersion) {
final normalized = lastSeenVersion?.trim();
if (normalized != null && normalized.isNotEmpty) {
return normalized;
}
return PreferencesStore.getBool(
PreferenceKeys.releaseNotesExistingInstallAtBootstrap,
) ==
true
? releaseNotesLegacyBaselineVersion
: null;
}
bool _hasExistingConfiguration() {
final activeServerId = PreferencesStore.getString(
PreferenceKeys.activeServerId,
);
final preferredBackend = PreferencesStore.getString(
PreferenceKeys.preferredBackend,
);
return (activeServerId != null && activeServerId.trim().isNotEmpty) ||
preferredBackend == 'owui' ||
preferredBackend == 'direct' ||
preferredBackend == 'hermes' ||
PreferencesStore.getBool(PreferenceKeys.directConnectionsConfigured) ==
true ||
PreferencesStore.getBool(PreferenceKeys.hermesEnabled) == true;
}