onedirve and google drive

This commit is contained in:
Courtney Arnold 2026-08-14 17:30:31 -05:00
parent a9bcec09b1
commit 901ec678a3
12 changed files with 373 additions and 29 deletions

View file

@ -234,11 +234,13 @@ class AppState extends ChangeNotifier {
Future<void> chooseCloudFolder({
required String parentId,
required String breadcrumbPath,
String? currentFolderName,
}) async {
final sync = cloudSync;
if (sync == null) return;
final folderId = await sync.selectAppFolder(parentId);
final folderId =
await sync.selectAppFolder(parentId, currentFolderName: currentFolderName);
cloudFolderPath = breadcrumbPath;
final prefs = await SharedPreferences.getInstance();
@ -399,6 +401,18 @@ class AppState extends ChangeNotifier {
}
}
/// Exact match against an active vehicle's VIN — same comparison
/// [DatabaseService.vinExists] does, not case-insensitive, since VIN
/// isn't normalized to any particular case on manual entry (only OCR
/// scanning uppercases it).
Vehicle? vehicleByVin(String vin) {
try {
return vehicles.firstWhere((v) => v.vin == vin);
} catch (_) {
return null;
}
}
Future<void> _persist() async {
await _refreshFromDatabase();
notifyListeners();

View file

@ -5,7 +5,7 @@ import 'dart:io';
/// exact name wherever the user points it, so two devices pointed at the
/// same shared parent location converge on the same data regardless of
/// which provider they're using.
const appFolderName = 'MO-Fuel-Tax-Back';
const appFolderName = 'Show Me The Fuel Refund';
const receiptsFolderName = 'receipts';
const dataFileName = 'fuel_tax_tracker.db';

View file

@ -12,7 +12,7 @@ import 'oauth_pkce.dart';
///
/// Unlike Google Drive, Dropbox's API is fundamentally *path*-addressed,
/// not ID-addressed. Rather than fight that, [DropboxSession] treats a
/// folder's own Dropbox path (e.g. "/MO-Fuel-Tax-Back") as its "id" for
/// folder's own Dropbox path (e.g. "/Show Me The Fuel Refund") as its "id" for
/// purposes of the generic [CloudStorageSession] interface — an
/// implementation detail entirely inside this file, invisible to
/// [CloudSyncService].

View file

@ -13,7 +13,8 @@ class CloudOAuthConfig {
/// The Web application OAuth client ID. Required for sign-in to work on
/// Android.
static const String? googleAndroidServerClientId = null; // TODO: fill in
static const String? googleAndroidServerClientId =
'871282023812-v230gah5qimen6kaa2mh1usl8l5otnio.apps.googleusercontent.com';
/// The iOS OAuth client ID. Leave null if GIDClientID is instead set
/// directly in ios/Runner/Info.plist.
@ -24,7 +25,7 @@ class CloudOAuthConfig {
// From a "Full Dropbox" access app at dropbox.com/developers/apps.
/// The app's key (client ID for OAuth2 PKCE — no secret needed).
static const String? dropboxAppKey = 'id43qmk09hilpgk';
static const String? dropboxAppKey = 'x79aoq4zhhmu0a0';
/// Custom URL scheme redirect registered in the Dropbox app console.
/// The scheme "mofueltaxback-dropbox" is already wired up in
@ -41,12 +42,12 @@ class CloudOAuthConfig {
// application" platform.
/// The Application (client) ID from the Azure app registration.
static const String? oneDriveClientId = null; // TODO: fill in
static const String? oneDriveClientId = '0574b661-1b12-44d8-86f0-ee59361fad1c';
/// Custom URL scheme redirect registered in Azure. The scheme
/// "mofueltaxback-onedrive" is already wired up in AndroidManifest.xml /
/// Info.plist, so unless you have a reason to pick a different scheme,
/// register and use exactly:
/// "mofueltaxback-onedrive://auth"
static const String? oneDriveRedirectUri = null; // TODO: fill in
static const String? oneDriveRedirectUri = 'mofueltaxback-onedrive://auth';
}

View file

@ -70,14 +70,24 @@ class CloudSyncService {
_lastKnownRemoteVersionTag = null;
}
/// Finds-or-creates the `MO-Fuel-Tax-Back` folder under [parentId] (a
/// folder the user picked in the folder browser) and configures this
/// 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.
Future<String> selectAppFolder(String parentId) async {
///
/// If the user picked a folder that's *already* named
/// `Show Me The Fuel Refund` — [currentFolderName] carries that name up
/// from the browser — [parentId] is used directly instead of nesting
/// another same-named folder inside it. Otherwise a folder picked at
/// "My Files" root would end up as `/Show Me The Fuel Refund` on first
/// 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`.
Future<String> selectAppFolder(String parentId, {String? currentFolderName}) async {
final session = provider.beginSession();
try {
final folderId =
await session.findOrCreateFolder(parentId: parentId, name: appFolderName);
final folderId = currentFolderName == appFolderName
? parentId
: await session.findOrCreateFolder(parentId: parentId, name: appFolderName);
configure(folderId);
return folderId;
} finally {