Ad and purchases enabled (still need actual testing)
This commit is contained in:
parent
2fcc6dcab7
commit
faf319322a
35 changed files with 1676 additions and 34 deletions
|
|
@ -70,9 +70,11 @@ class CloudSyncService {
|
|||
_lastKnownRemoteVersionTag = null;
|
||||
}
|
||||
|
||||
/// Finds-or-creates the `Show Me The Fuel Refund` folder under [parentId]
|
||||
/// (a folder the user picked in the folder browser) and configures this
|
||||
/// service to use it. Returns the resulting folder ID.
|
||||
/// Points this service at the `Show Me The Fuel Refund` folder under
|
||||
/// [parentId] (a folder the user picked in the folder browser, or —
|
||||
/// see [AppState.connectProvider] — the assumed root location a fresh
|
||||
/// connection defaults to) and configures this service to use it.
|
||||
/// Returns the resulting folder ID.
|
||||
///
|
||||
/// If the user picked a folder that's *already* named
|
||||
/// `Show Me The Fuel Refund` — [currentFolderName] carries that name up
|
||||
|
|
@ -82,12 +84,45 @@ class CloudSyncService {
|
|||
/// setup, but re-picking that same folder later (e.g. after reinstalling)
|
||||
/// would double it up as `/Show Me The Fuel Refund/Show Me The Fuel
|
||||
/// Refund`.
|
||||
///
|
||||
/// Otherwise, three cases:
|
||||
/// - A same-named folder already exists directly under [parentId] (e.g.
|
||||
/// one someone else already set up there to share) — adopt it as-is,
|
||||
/// the same convergence behavior as before, so two people pointed at
|
||||
/// the same shared parent end up sharing one app folder either way.
|
||||
/// - This service already has an app folder configured somewhere else
|
||||
/// (from a previous [selectAppFolder] call, or the root default a
|
||||
/// fresh connection starts with) and [parentId] has no folder of its
|
||||
/// own yet — *move* the existing one there via
|
||||
/// [CloudStorageSession.moveFolder], preserving its contents, rather
|
||||
/// than creating a fresh empty folder and abandoning the old one with
|
||||
/// all its synced data still in it.
|
||||
/// - Neither of the above (nothing configured yet, nothing at the
|
||||
/// destination) — create a fresh one, same as always.
|
||||
Future<String> selectAppFolder(String parentId, {String? currentFolderName}) async {
|
||||
final session = provider.beginSession();
|
||||
try {
|
||||
final folderId = currentFolderName == appFolderName
|
||||
? parentId
|
||||
: await session.findOrCreateFolder(parentId: parentId, name: appFolderName);
|
||||
if (currentFolderName == appFolderName) {
|
||||
configure(parentId);
|
||||
return parentId;
|
||||
}
|
||||
|
||||
CloudFolder? existingAtDestination;
|
||||
for (final folder in await session.listFolders(parentId: parentId)) {
|
||||
if (folder.name == appFolderName) {
|
||||
existingAtDestination = folder;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
final String folderId;
|
||||
if (existingAtDestination != null) {
|
||||
folderId = existingAtDestination.id;
|
||||
} else if (_appFolderId != null) {
|
||||
folderId = await session.moveFolder(folderId: _appFolderId!, newParentId: parentId);
|
||||
} else {
|
||||
folderId = await session.findOrCreateFolder(parentId: parentId, name: appFolderName);
|
||||
}
|
||||
configure(folderId);
|
||||
return folderId;
|
||||
} finally {
|
||||
|
|
@ -106,9 +141,17 @@ class CloudSyncService {
|
|||
/// treats it as abandoned (e.g. that device crashed or went offline
|
||||
/// mid-sync) and deletes it rather than waiting forever. Defaults to 10
|
||||
/// minutes, matching [defaultStaleLockMinutes] in app_state.dart.
|
||||
///
|
||||
/// [beforeUpload], if given, is awaited once — after any pull/merge of
|
||||
/// remote changes has finished, but before anything local gets uploaded
|
||||
/// (pending receipt photos or the database snapshot itself). This is the
|
||||
/// one hook [AppState] uses to show the app's single ad placement, since
|
||||
/// it's meant to run before *pushing* local data up, not before *pulling*
|
||||
/// remote data down.
|
||||
Future<SyncResult> syncNow({
|
||||
bool keepLocalReceiptCopies = false,
|
||||
Duration staleLockAge = const Duration(minutes: 10),
|
||||
Future<void> Function()? beforeUpload,
|
||||
}) async {
|
||||
final appFolderId = _appFolderId;
|
||||
if (!provider.isSignedIn || appFolderId == null) {
|
||||
|
|
@ -137,6 +180,10 @@ class CloudSyncService {
|
|||
await _pullAndMerge(session, remoteInfo.id);
|
||||
}
|
||||
|
||||
if (beforeUpload != null) {
|
||||
await beforeUpload();
|
||||
}
|
||||
|
||||
final allReceiptsUploaded =
|
||||
await _uploadPendingReceipts(session, keepLocalCopies: keepLocalReceiptCopies);
|
||||
|
||||
|
|
@ -178,6 +225,21 @@ class CloudSyncService {
|
|||
try {
|
||||
await db.execute(mergeVehiclesSql);
|
||||
await db.execute(mergeFuelEntriesSql);
|
||||
|
||||
// ad_free_entitlement is a newer table than vehicles/fuel_entries —
|
||||
// unlike those two (present since the very first schema version, so
|
||||
// any remote snapshot ever pushed already has them), a remote
|
||||
// snapshot pushed before this table existed genuinely won't have
|
||||
// it. Merging against it unconditionally would throw ("no such
|
||||
// table") on exactly that snapshot; skipping when absent just means
|
||||
// "that older snapshot has no entitlement info to contribute",
|
||||
// which is correct — local's own value (if any) is left as-is.
|
||||
final remoteHasEntitlementTable = (await db.rawQuery(
|
||||
"SELECT 1 FROM remote_db.sqlite_master WHERE type = 'table' AND name = 'ad_free_entitlement'",
|
||||
)).isNotEmpty;
|
||||
if (remoteHasEntitlementTable) {
|
||||
await db.execute(mergeAdFreeEntitlementSql);
|
||||
}
|
||||
} finally {
|
||||
try {
|
||||
await db.execute('DETACH DATABASE remote_db');
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue