Skip to content

Commit

Permalink
Google drive api support (#31)
Browse files Browse the repository at this point in the history
* Process termination

* Use google drive api V3 to terminate process

* Add upload button in preview

* Fix lint

* Fix error builder in network image
  • Loading branch information
cp-pratik-k authored Apr 19, 2024
1 parent 20a0a6d commit a70e56b
Show file tree
Hide file tree
Showing 35 changed files with 587 additions and 255 deletions.
Binary file modified .DS_Store
Binary file not shown.
8 changes: 8 additions & 0 deletions .idea/libraries/Dart_Packages.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions .idea/libraries/Flutter_Plugins.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions app/assets/locales/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"load_local_media_button_text": "Load local media",

"theme_text": "Theme",
"notification_text": "Notification",
"light_theme_text": "Light",
"dark_theme_text": "Dark",
"system_theme_text": "System",
Expand Down
2 changes: 1 addition & 1 deletion app/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -138,4 +138,4 @@ SPEC CHECKSUMS:

PODFILE CHECKSUM: 819463e6a0290f5a72f145ba7cde16e8b6ef0796

COCOAPODS: 1.14.3
COCOAPODS: 1.15.2
13 changes: 8 additions & 5 deletions app/ios/Runner/Base.lproj/Main.storyboard
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="22154" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
<device id="retina6_12" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22130"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--Flutter View Controller-->
Expand All @@ -14,13 +16,14 @@
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="109" y="-77"/>
</scene>
</scenes>
</document>
11 changes: 7 additions & 4 deletions app/lib/ui/flow/accounts/accounts_screen_view_model.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'dart:async';
import 'package:data/services/auth_service.dart';
import 'package:data/services/device_service.dart';
import 'package:data/storage/app_preferences.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:google_sign_in/google_sign_in.dart';
Expand All @@ -12,18 +13,19 @@ final accountsStateNotifierProvider =
(ref) => AccountsStateNotifier(
ref.read(deviceServiceProvider),
ref.read(authServiceProvider),
ref.read(AppPreferences.canTakeAutoBackUpInGoogleDrive.notifier),
),
);

class AccountsStateNotifier extends StateNotifier<AccountsState> {
final DeviceService _deviceService;
final AuthService _authService;
StreamSubscription? _googleAccountSubscription;
StateController<bool> canTakeAutoBackUpInGoogleDrive;

AccountsStateNotifier(
this._deviceService,
this._authService,
) : super(AccountsState(googleAccount: _authService.googleAccount));
AccountsStateNotifier(this._deviceService, this._authService,
this.canTakeAutoBackUpInGoogleDrive)
: super(AccountsState(googleAccount: _authService.googleAccount));

Future<void> init() async {
_getAppVersion();
Expand Down Expand Up @@ -54,6 +56,7 @@ class AccountsStateNotifier extends StateNotifier<AccountsState> {
Future<void> signOutWithGoogle() async {
try {
await _authService.signOutWithGoogle();
canTakeAutoBackUpInGoogleDrive.state = false;
} catch (e) {
state = state.copyWith(error: e);
}
Expand Down
11 changes: 11 additions & 0 deletions app/lib/ui/flow/accounts/components/settings_action_list.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,25 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:style/buttons/buttons_list.dart';
import 'package:style/buttons/segmented_button.dart';
import 'package:style/buttons/switch.dart';

class SettingsActionList extends ConsumerWidget {
const SettingsActionList({super.key});

@override
Widget build(BuildContext context, WidgetRef ref) {
final isDarkMode = ref.watch(AppPreferences.isDarkMode);
final notifications = ref.watch(AppPreferences.notifications);
return ActionList(buttons: [
ActionListButton(
title: context.l10n.notification_text,
trailing: AppSwitch(
value: notifications,
onChanged: (value) {
ref.read(AppPreferences.notifications.notifier).state = value;
},
),
),
ActionListButton(
title: context.l10n.theme_text,
trailing: AppSegmentedButton(
Expand Down
24 changes: 14 additions & 10 deletions app/lib/ui/flow/home/components/hint_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ class HintView extends StatelessWidget {
child: Column(
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: Padding(
padding: const EdgeInsets.only(top: 16, left: 16),
padding: const EdgeInsets.only(top: 4, left: 16),
child: Text(
title,
style: AppTextStyles.subtitle2.copyWith(
Expand All @@ -43,14 +43,18 @@ class HintView extends StatelessWidget {
),
),
),
ActionButton(
backgroundColor: context.colorScheme.containerNormal,
size: 28,
onPressed: onClose,
icon: Icon(
CupertinoIcons.xmark,
color: context.colorScheme.textSecondary,
size: 18,
Padding(
padding: const EdgeInsets.all(8.0).copyWith(bottom: 4),
child: ActionButton(
backgroundColor: context.colorScheme.containerNormal,
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
size: 28,
onPressed: onClose,
icon: Icon(
CupertinoIcons.xmark,
color: context.colorScheme.textSecondary,
size: 18,
),
),
),
],
Expand Down
2 changes: 2 additions & 0 deletions app/lib/ui/flow/home/home_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ class _HomeScreenState extends ConsumerState<HomeScreen> {
child: Padding(
padding: const EdgeInsets.only(right: 8.0),
child: ActionButton(
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
size: 36,
backgroundColor: context.colorScheme.containerNormal,
onPressed: () {
Expand All @@ -87,6 +88,7 @@ class _HomeScreenState extends ConsumerState<HomeScreen> {
ActionButton(
size: 36,
backgroundColor: context.colorScheme.containerNormal,
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
onPressed: () {
AppRouter.accounts.push(context);
},
Expand Down
28 changes: 25 additions & 3 deletions app/lib/ui/flow/home/home_screen_view_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import 'package:data/repositories/google_drive_process_repo.dart';
import 'package:data/services/auth_service.dart';
import 'package:data/services/google_drive_service.dart';
import 'package:data/services/local_media_service.dart';
import 'package:data/storage/app_preferences.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:google_sign_in/google_sign_in.dart';
Expand All @@ -19,16 +20,23 @@ part 'home_screen_view_model.freezed.dart';
final homeViewStateNotifier =
StateNotifierProvider.autoDispose<HomeViewStateNotifier, HomeViewState>(
(ref) {
return HomeViewStateNotifier(
final homeView = HomeViewStateNotifier(
ref.read(localMediaServiceProvider),
ref.read(googleDriveServiceProvider),
ref.read(authServiceProvider),
ref.read(googleDriveProcessRepoProvider),
ref.read(AppPreferences.canTakeAutoBackUpInGoogleDrive),
);

ref.listen(AppPreferences.canTakeAutoBackUpInGoogleDrive, (previous, next) {
homeView.updateAutoBackUpStatus(next);
});
return homeView;
});

class HomeViewStateNotifier extends StateNotifier<HomeViewState>
with HomeViewModelHelperMixin {
bool _autoBackUpStatus;
final AuthService _authService;
final GoogleDriveService _googleDriveService;
final GoogleDriveProcessRepo _googleDriveProcessRepo;
Expand All @@ -43,12 +51,26 @@ class HomeViewStateNotifier extends StateNotifier<HomeViewState>
bool _isMaxLocalMediaLoaded = false;

HomeViewStateNotifier(this._localMediaService, this._googleDriveService,
this._authService, this._googleDriveProcessRepo)
this._authService, this._googleDriveProcessRepo, this._autoBackUpStatus)
: super(const HomeViewState()) {
_listenUserGoogleAccount();
_googleDriveProcessRepo.setBackUpFolderId(_backUpFolderId);
_googleDriveProcessRepo.addListener(_listenGoogleDriveProcess);
_loadInitialMedia();
_checkAutoBackUp();
}

void updateAutoBackUpStatus(bool status) {
_autoBackUpStatus = status;
_checkAutoBackUp();
}

void _checkAutoBackUp() {
if (_autoBackUpStatus) {
_googleDriveProcessRepo.uploadMediasInGoogleDrive(
medias: state.medias.valuesWhere((element) => element.isLocalStored),
);
}
}

void _listenUserGoogleAccount() {
Expand Down Expand Up @@ -115,7 +137,7 @@ class HomeViewStateNotifier extends StateNotifier<HomeViewState>
_googleDriveProcessRepo.downloadQueue.isNotEmpty);
}

void _loadInitialMedia() async {
Future<void> _loadInitialMedia() async {
state = state.copyWith(loading: true, error: null);
final hasAccess = await _localMediaService.requestPermission();
state = state.copyWith(hasLocalMediaAccess: hasAccess, loading: false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'package:cloud_gallery/components/app_page.dart';
import 'package:cloud_gallery/components/error_view.dart';
import 'package:cloud_gallery/domain/extensions/context_extensions.dart';
import 'package:data/models/media/media.dart';
import 'package:data/models/media/media_extension.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../../../domain/extensions/widget_extensions.dart';
Expand All @@ -28,8 +29,9 @@ class _ImagePreviewScreenState extends ConsumerState<ImagePreview> {
void initState() {
if (!widget.media.sources.contains(AppMediaSource.local)) {
notifier = ref.read(networkImagePreviewStateNotifierProvider.notifier);
runPostFrame(() {
notifier.loadImage(widget.media.id);
runPostFrame(() async {
await notifier.loadImageFromGoogleDrive(
id: widget.media.id, extension: widget.media.extension);
});
}
super.initState();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import 'dart:typed_data';
import 'dart:io';
import 'package:cloud_gallery/domain/extensions/context_extensions.dart';
import 'package:data/models/media/media.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:style/indicators/circular_progress_indicator.dart';
import '../../../../../components/app_page.dart';
import '../../../../../components/error_view.dart';
import 'network_image_preview_view_model.dart';

Expand All @@ -18,18 +19,24 @@ class NetworkImagePreview extends ConsumerWidget {

if (state.loading) {
return Center(child: AppCircularProgressIndicator(value: state.progress));
} else if (state.mediaBytes != null) {
} else if (state.filePath != null) {
return Hero(
tag: media,
child: Image.memory(Uint8List.fromList(state.mediaBytes!),
fit: BoxFit.fitWidth),
child: Image.file(File(state.filePath!), fit: BoxFit.fitWidth,
errorBuilder: (context, error, stackTrace) {
return AppPage(
body: ErrorView(
title: context.l10n.unable_to_load_media_error,
message: context.l10n.unable_to_load_media_message,
));
}),
);
} else if (state.error != null) {
return ErrorView(
title: context.l10n.unable_to_load_media_error,
message: context.l10n.unable_to_load_media_message,
);
}
return const Placeholder();
return const SizedBox();
}
}
Loading

0 comments on commit a70e56b

Please sign in to comment.