Skip to content

Commit

Permalink
(#110) Update example project to cover openDocument API
Browse files Browse the repository at this point in the history
  • Loading branch information
alexrintt committed Nov 11, 2022
1 parent 3ad5b54 commit bb9ea89
Show file tree
Hide file tree
Showing 4 changed files with 228 additions and 97 deletions.
80 changes: 3 additions & 77 deletions example/lib/screens/file_explorer/file_explorer_card.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,13 @@ import 'dart:io';
import 'dart:math';
import 'dart:typed_data';

import 'package:fl_toast/fl_toast.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:shared_storage/shared_storage.dart';

import '../../theme/spacing.dart';
import '../../utils/apply_if_not_null.dart';
import '../../utils/confirm_decorator.dart';
import '../../utils/disabled_text_style.dart';
import '../../utils/document_file_utils.dart';
import '../../utils/format_bytes.dart';
import '../../utils/inline_span.dart';
import '../../utils/mime_types.dart';
Expand Down Expand Up @@ -241,7 +239,7 @@ class _FileExplorerCardState extends State<FileExplorerCard> {
}

Widget _buildOpenWithButton() =>
Button('Open with', onTap: _openFileWithExternalApp);
Button('Open with', onTap: _currentUri.openWithExternalApp);

Widget _buildDocumentSimplifiedTile() {
return ListTile(
Expand Down Expand Up @@ -319,60 +317,6 @@ class _FileExplorerCardState extends State<FileExplorerCard> {

String get _mimeTypeOrEmpty => _file.type ?? '';

Future<void> _showFileContents() async {
if (_isDirectory) return;

const k10mb = 1024 * 1024 * 10;

if (!_mimeTypeOrEmpty.startsWith(kTextMime) &&
!_mimeTypeOrEmpty.startsWith(kImageMime)) {
if (_mimeTypeOrEmpty == kApkMime) {
return showTextToast(
text:
'Requesting to install a package (.apk) is not currently supported, to request this feature open an issue at github.com/alexrintt/shared-storage/issues',
context: context,
);
}

return _openFileWithExternalApp();
}

// Too long, will take too much time to read
if (_sizeInBytes > k10mb) {
return showTextToast(
text: 'File too long to open',
context: context,
);
}

content = await getDocumentContent(_file.uri);

if (content != null) {
final isImage = _mimeTypeOrEmpty.startsWith(kImageMime);

await showModalBottomSheet(
context: context,
builder: (context) {
if (isImage) {
return Image.memory(content!);
}

final contentAsString = String.fromCharCodes(content!);

final fileIsEmpty = contentAsString.isEmpty;

return Container(
padding: k8dp.all,
child: Text(
fileIsEmpty ? 'This file is empty' : contentAsString,
style: fileIsEmpty ? disabledTextStyle() : null,
),
);
},
);
}
}

Future<void> _deleteDocument() async {
final deleted = await delete(_currentUri);

Expand Down Expand Up @@ -436,24 +380,6 @@ class _FileExplorerCardState extends State<FileExplorerCard> {
}
}

Future<void> _openFileWithExternalApp() async {
final uri = _currentUri;

try {
final launched = await openDocumentFile(uri);

if (launched ?? false) {
print('Successfully opened $uri');
} else {
print('Failed to launch $uri');
}
} on PlatformException {
print(
"There's no activity associated with the file type of this Uri: $uri",
);
}
}

Future<void> _openDirectory() async {
if (_isDirectory) {
_openFolderFileListPage(_file.uri);
Expand All @@ -463,7 +389,7 @@ class _FileExplorerCardState extends State<FileExplorerCard> {
@override
Widget build(BuildContext context) {
return SimpleCard(
onTap: _isDirectory ? _openDirectory : _showFileContents,
onTap: _isDirectory ? _openDirectory : () => _file.showContents(context),
children: [
if (_expanded) ...[
_buildThumbnail(size: 50),
Expand Down
99 changes: 88 additions & 11 deletions example/lib/screens/granted_uris/granted_uri_card.dart
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import 'package:fl_toast/fl_toast.dart';
import 'package:flutter/material.dart';
import 'package:shared_storage/shared_storage.dart';

import '../../theme/spacing.dart';
import '../../utils/disabled_text_style.dart';
import '../../utils/document_file_utils.dart';
import '../../widgets/buttons.dart';
import '../../widgets/key_value_text.dart';
import '../../widgets/simple_card.dart';
import '../file_explorer/file_explorer_card.dart';
import '../file_explorer/file_explorer_page.dart';

class GrantedUriCard extends StatefulWidget {
Expand Down Expand Up @@ -55,19 +59,65 @@ class _GrantedUriCardState extends State<GrantedUriCard> {
);
}

List<Widget> _getTreeAvailableOptions() {
return [
ActionButton(
'Create sample file',
onTap: () => _appendSampleFile(
widget.permissionUri.uri,
),
),
ActionButton(
'Open tree here',
onTap: () => openDocumentTree(initialUri: widget.permissionUri.uri),
)
];
}

DocumentFile? documentFile;
bool loading = false;
String? error;

Future<void> _loadDocumentFile() async {
loading = true;
setState(() {});

documentFile = await widget.permissionUri.uri.toDocumentFile();
loading = false;

if (mounted) setState(() {});
}

Future<void> _showDocumentFileContents() async {
try {
final documentFile = await widget.permissionUri.uri.toDocumentFile();

if (mounted) documentFile?.showContents(context);
} catch (e) {
error = e.toString();
}
}

List<Widget> _getDocumentAvailableOptions() {
return [
ActionButton(
'Open document',
onTap: _showDocumentFileContents,
),
ActionButton(
'Load extra document data linked to this permission',
onTap: _loadDocumentFile,
),
];
}

Widget _buildAvailableActions() {
return Wrap(
children: [
ActionButton(
'Create Sample File',
onTap: () => _appendSampleFile(
widget.permissionUri.uri,
),
),
ActionButton(
'Open Tree Here',
onTap: () => openDocumentTree(initialUri: widget.permissionUri.uri),
),
if (widget.permissionUri.isTreeDocumentFile)
..._getTreeAvailableOptions()
else
..._getDocumentAvailableOptions(),
Padding(padding: k2dp.all),
DangerButton(
'Revoke',
Expand All @@ -86,17 +136,44 @@ class _GrantedUriCardState extends State<GrantedUriCard> {
'isReadPermission': '${widget.permissionUri.isReadPermission}',
'persistedTime': '${widget.permissionUri.persistedTime}',
'uri': Uri.decodeFull('${widget.permissionUri.uri}'),
'isTreeDocumentFile': '${widget.permissionUri.isTreeDocumentFile}',
},
);
}

@override
Widget build(BuildContext context) {
return SimpleCard(
onTap: _openListFilesPage,
onTap: widget.permissionUri.isTreeDocumentFile
? _openListFilesPage
: _showDocumentFileContents,
children: [
Padding(
padding: k2dp.all.copyWith(top: k8dp, bottom: k8dp),
child: Icon(
widget.permissionUri.isTreeDocumentFile
? Icons.folder
: Icons.file_copy_sharp,
color: disabledColor(),
),
),
_buildGrantedUriMetadata(),
_buildAvailableActions(),
if (loading)
const SizedBox(
height: 20,
width: 20,
child: CircularProgressIndicator(),
)
else if (error != null)
Text('Error was thrown: $error')
else if (documentFile != null)
FileExplorerCard(
documentFile: documentFile!,
didUpdateDocument: (updatedDocumentFile) {
documentFile = updatedDocumentFile;
},
)
],
);
}
Expand Down
56 changes: 47 additions & 9 deletions example/lib/screens/granted_uris/granted_uris_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:shared_storage/shared_storage.dart';

import '../../theme/spacing.dart';
import '../../utils/disabled_text_style.dart';
import '../../widgets/light_text.dart';
import 'granted_uri_card.dart';

Expand All @@ -13,7 +14,13 @@ class GrantedUrisPage extends StatefulWidget {
}

class _GrantedUrisPageState extends State<GrantedUrisPage> {
List<UriPermission>? persistedPermissionUris;
List<UriPermission>? __persistedPermissionUris;
List<UriPermission>? get _persistedPermissionUris {
if (__persistedPermissionUris == null) return null;

return List.from(__persistedPermissionUris!)
..sort((a, z) => z.persistedTime - a.persistedTime);
}

@override
void initState() {
Expand All @@ -23,7 +30,7 @@ class _GrantedUrisPageState extends State<GrantedUrisPage> {
}

Future<void> _loadPersistedUriPermissions() async {
persistedPermissionUris = await persistedUriPermissions();
__persistedPermissionUris = await persistedUriPermissions();

if (mounted) setState(() => {});
}
Expand All @@ -41,6 +48,20 @@ class _GrantedUrisPageState extends State<GrantedUrisPage> {
await _loadPersistedUriPermissions();
}

Future<void> _openDocument() async {
const kDownloadsFolder =
'content://com.android.externalstorage.documents/tree/primary%3ADownloads/document/primary%3ADownloads';

final List<Uri>? selectedDocumentUris = await openDocument(
initialUri: Uri.parse(kDownloadsFolder),
multiple: true,
);

if (selectedDocumentUris == null) return;

await _loadPersistedUriPermissions();
}

Widget _buildNoFolderAllowedYetWarning() {
return Padding(
padding: k8dp.all,
Expand All @@ -66,22 +87,39 @@ class _GrantedUrisPageState extends State<GrantedUrisPage> {
delegate: SliverChildListDelegate(
[
Center(
child: TextButton(
onPressed: _openDocumentTree,
child: const Text('New allowed folder'),
child: Wrap(
alignment: WrapAlignment.center,
crossAxisAlignment: WrapCrossAlignment.center,
runAlignment: WrapAlignment.center,
children: [
TextButton(
onPressed: _openDocumentTree,
child: const Text('New allowed folder'),
),
const Padding(padding: EdgeInsets.all(k2dp)),
TextButton(
onPressed: _openDocument,
child: const Text('New allowed files'),
),
],
),
),
if (persistedPermissionUris != null)
if (persistedPermissionUris!.isEmpty)
if (_persistedPermissionUris != null)
if (_persistedPermissionUris!.isEmpty)
_buildNoFolderAllowedYetWarning()
else
for (final permissionUri in persistedPermissionUris!)
for (final permissionUri in _persistedPermissionUris!)
GrantedUriCard(
permissionUri: permissionUri,
onChange: _loadPersistedUriPermissions,
)
else
const Text('Loading...'),
Center(
child: Text(
'Loading...',
style: disabledTextStyle(),
),
),
],
),
),
Expand Down
Loading

0 comments on commit bb9ea89

Please sign in to comment.