Skip to content

Commit

Permalink
Merge pull request #235 from humhub/internal-f-52-long-press-download
Browse files Browse the repository at this point in the history
IOS: Long press download and File loadig animation
  • Loading branch information
luke- authored Sep 26, 2024
2 parents 2d8701e + f119e5a commit 9d4fbde
Show file tree
Hide file tree
Showing 11 changed files with 343 additions and 146 deletions.
2 changes: 2 additions & 0 deletions ios/Runner/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@
<false/>
<key>NSCameraUsageDescription</key>
<string>We need access to your camera to take photos and videos for sharing in the app.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>We need access your photo library to allow you to upload, view, and manage photos within the app.</string>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
Expand Down
153 changes: 120 additions & 33 deletions lib/flavored/web_view.f.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,15 @@ import 'package:humhub/app_flavored.dart';
import 'package:humhub/flavored/models/humhub.f.dart';
import 'package:humhub/util/auth_in_app_browser.dart';
import 'package:humhub/models/channel_message.dart';
import 'package:humhub/util/black_list_rules.dart';
import 'package:humhub/util/const.dart';
import 'package:humhub/util/extensions.dart';
import 'package:humhub/util/loading_provider.dart';
import 'package:humhub/util/notifications/init_from_push.dart';
import 'package:humhub/util/notifications/plugin.dart';
import 'package:humhub/util/push/provider.dart';
import 'package:humhub/util/show_dialog.dart';
import 'package:humhub/util/web_view_global_controller.dart';
import 'package:loggy/loggy.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:humhub/util/file_handler.dart';
Expand All @@ -37,8 +36,9 @@ class FlavoredWebViewState extends ConsumerState<WebViewF> {
late AuthInAppBrowser _authBrowser;
HeadlessInAppWebView? headlessWebView;
late HumHubF instance;

final _scaffoldKey = GlobalKey<ScaffoldState>();
late PullToRefreshController pullToRefreshController;
late double downloadProgress = 0;

@override
void initState() {
Expand Down Expand Up @@ -73,6 +73,7 @@ class FlavoredWebViewState extends ConsumerState<WebViewF> {
return WillPopScope(
onWillPop: () => exitApp(context, ref),
child: Scaffold(
key: _scaffoldKey,
backgroundColor: HexColor(instance.manifest.themeColor),
body: SafeArea(
bottom: false,
Expand Down Expand Up @@ -121,11 +122,22 @@ class FlavoredWebViewState extends ConsumerState<WebViewF> {
InAppWebViewController controller, NavigationAction action) async {
// 1st check if url is not def. app url and open it in a browser or inApp.
WebViewGlobalController.ajaxSetHeaders(headers: instance.customHeaders);
final url = action.request.url!.origin;
final url = action.request.url!.rawValue;

/// First BLOCK everything that rules out as blocked.
if (BlackListRules.check(url)) {
return NavigationActionPolicy.CANCEL;
}
// For SSO
if (!url.startsWith(instance.manifest.baseUrl) && action.isForMainFrame) {
_authBrowser.launchUrl(action.request);
return NavigationActionPolicy.CANCEL;
}
// For all other external links
if (!url.startsWith(instance.manifest.baseUrl) && !action.isForMainFrame) {
await launchUrl(action.request.url!.uriValue, mode: LaunchMode.externalApplication);
return NavigationActionPolicy.CANCEL;
}
// 2nd Append customHeader if url is in app redirect and CANCEL the requests without custom headers
if (Platform.isAndroid ||
action.navigationType == NavigationType.LINK_ACTIVATED ||
Expand Down Expand Up @@ -162,7 +174,7 @@ class FlavoredWebViewState extends ConsumerState<WebViewF> {
Future<bool> _onCreateWindow(InAppWebViewController controller, CreateWindowAction createWindowAction) async {
final urlToOpen = createWindowAction.request.url;
if (urlToOpen == null) return Future.value(false);
if (WebViewGlobalController.openCreateWindowInWebView(ref, urlToOpen.rawValue)) {
if (WebViewGlobalController.openCreateWindowInWebView(url: urlToOpen.rawValue, manifest: instance.manifest)) {
controller.loadUrl(urlRequest: createWindowAction.request);
return Future.value(false);
}
Expand Down Expand Up @@ -219,12 +231,6 @@ class FlavoredWebViewState extends ConsumerState<WebViewF> {
headers: instance.customHeaders,
);
}
var status = await Permission.notification.status;
// status.isDenied: The user has previously denied the notification permission
// !status.isGranted: The user has never been asked for the notification permission
bool wasAskedBefore = await NotificationPlugin.hasAskedPermissionBefore();
// ignore: use_build_context_synchronously
if (status != PermissionStatus.granted && !wasAskedBefore) ShowDialog.of(context).notificationPermission();
break;
case ChannelAction.updateNotificationCount:
if (message.count != null) FlutterAppBadger.updateBadgeCount(message.count!);
Expand Down Expand Up @@ -275,30 +281,111 @@ class FlavoredWebViewState extends ConsumerState<WebViewF> {
}

void _onDownloadStartRequest(InAppWebViewController controller, DownloadStartRequest downloadStartRequest) async {
PersistentBottomSheetController? persistentController;
//bool isBottomSheetVisible = false;

// Initialize the download progress
downloadProgress = 0;

// Timer to control when to show the bottom sheet
Timer? downloadTimer;
bool isDone = false;

FileHandler(
downloadStartRequest: downloadStartRequest,
controller: controller,
onSuccess: (File file, String filename) {
scaffoldMessengerStateKey.currentState?.showSnackBar(
SnackBar(
content: Text('${AppLocalizations.of(context)!.file_download}: $filename'),
action: SnackBarAction(
label: AppLocalizations.of(context)!.open,
onPressed: () {
// Open the downloaded file
OpenFile.open(file.path);
},
),
),
);
},
onError: (er) {
scaffoldMessengerStateKey.currentState?.showSnackBar(
SnackBar(
content: Text(AppLocalizations.of(context)!.generic_error),
downloadStartRequest: downloadStartRequest,
controller: controller,
onSuccess: (File file, String filename) async {
// Hide the bottom sheet if it is visible
Navigator.popUntil(context, ModalRoute.withName(WebViewF.path));
isDone = true;
scaffoldMessengerStateKey.currentState?.showSnackBar(
SnackBar(
content: Text('${AppLocalizations.of(context)!.file_download}: $filename'),
action: SnackBarAction(
label: AppLocalizations.of(context)!.open,
onPressed: () {
OpenFile.open(file.path);
},
),
);
}).download();
),
);
},
onStart: () async {
downloadProgress = 0;
// Start the timer for 1 second
downloadTimer = Timer(const Duration(seconds: 1), () {
// Show the persistent bottom sheet if not already shown
if (!isDone) {
persistentController = _scaffoldKey.currentState!.showBottomSheet((context) {
return Container(
width: MediaQuery.of(context).size.width,
height: 100,
color: const Color(0xff313033),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 16),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"${AppLocalizations.of(context)!.downloading}...",
style: const TextStyle(fontWeight: FontWeight.bold, color: Colors.white),
),
Stack(
alignment: Alignment.center,
children: [
CircularProgressIndicator(
value: downloadProgress / 100,
backgroundColor: Colors.grey,
color: Colors.green,
),
downloadProgress.toStringAsFixed(0) == "100"
? const Icon(
Icons.check,
color: Colors.green,
size: 25,
)
: Text(
downloadProgress.toStringAsFixed(0),
style: const TextStyle(
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
],
),
],
),
),
);
});
}
});
},
onProgress: (progress) async {
downloadProgress = progress;
if (persistentController != null) {
persistentController!.setState!(() {});
}
},
onError: (er) {
downloadTimer?.cancel();
if (persistentController != null) {
Navigator.popUntil(context, ModalRoute.withName(WebViewF.path));
}
scaffoldMessengerStateKey.currentState?.showSnackBar(
SnackBar(
content: Text(AppLocalizations.of(context)!.generic_error),
),
);
},
).download();

// Ensure to cancel the timer if download finishes before 1 second
Future.delayed(const Duration(seconds: 1), () {
if (downloadProgress >= 100) {
downloadTimer?.cancel();
}
});
}

@override
Expand Down
4 changes: 1 addition & 3 deletions lib/l10n/app_de.arb
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,6 @@
"more_info_pro_edition": "Professional Edition",
"more_info_pro_edition_url": "https://www.humhub.com/de/professional-edition",

"notification_permission_popup_title": "Benachrichtigungen empfangen",
"notification_permission_popup_content": "Bitte aktiviere Benachrichtigungen für die HumHub App in deinen Geräteeinstellungen.",

"connectivity_popup_title": "Keine Verbindung möglich.",
"connectivity_popup_content": "Bitte überprüfe deine Internetverbindung und versuche es erneut.",

Expand All @@ -37,6 +34,7 @@

"enable_permissions": "Berechtigungen aktivieren.",

"downloading": "Herunterladen",
"settings": "Einstellungen",
"connect": "Verbinden",
"open": "Öffnen",
Expand Down
4 changes: 1 addition & 3 deletions lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,6 @@
"more_info_pro_edition": "Professional Edition",
"more_info_pro_edition_url": "https://www.humhub.com/en/professional-edition",

"notification_permission_popup_title": "Notification Permission",
"notification_permission_popup_content": "Please enable notifications for HumHub in the device settings",

"connectivity_popup_title": "No Connection",
"connectivity_popup_content": "Please check your internet connection and try again.",

Expand All @@ -38,6 +35,7 @@

"enable_permissions": "Enable permissions.",

"downloading": "Downloading",
"settings": "Settings",
"connect": "Connect",
"open": "Open",
Expand Down
4 changes: 1 addition & 3 deletions lib/l10n/app_fr.arb
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,6 @@
"more_info_pro_edition": "Édition Professionnelle",
"more_info_pro_edition_url": "https://www.humhub.com/fr/edition-professionnelle",

"notification_permission_popup_title": "Permission de notification",
"notification_permission_popup_content": "Veuillez activer les notifications pour HumHub dans les paramètres de l'appareil.",

"connectivity_popup_title": "Pas de connexion",
"connectivity_popup_content": "Veuillez vérifier votre connexion Internet et réessayer.",

Expand All @@ -37,6 +34,7 @@

"enable_permissions": "Activer les autorisations.",

"downloading": "Téléchargement",
"settings": "Paramètres",
"connect": "Connecter",
"open": "Ouvrir",
Expand Down
Loading

0 comments on commit 9d4fbde

Please sign in to comment.