Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add image_picker dependency and plugins for file selection on differe… #22

Merged
merged 8 commits into from
Jan 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
![sane_gallery logo](android/app/src/main/res/drawable-mdpi/android12splash.png)

<h1 style="font-weight: normal;">Sane<b>Gallery</b></h1>
<h1 style="font-weight: normal;">sane<b>Gallery</b></h1>

Sane**Gallery** is the Flutter reimplementation of [gallereasy](https://github.com/hoangph271/gallereasy), a web app for searching & saving GIFs.
sane**Gallery** is the Flutter reimplementation of [gallereasy](https://github.com/hoangph271/gallereasy), a web app for searching & saving GIFs.

## Deployed Web Version

Check out the live version of [SaneGallery on the Web.](https://sane-gallery.netlify.app/)
Check out the live version of [**saneGallery** on the Web.](https://sane-gallery.netlify.app/)

## Android Build

Expand Down
2 changes: 1 addition & 1 deletion android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:label="SaneGallery"
android:label="saneGallery"
android:name="${applicationName}"
android:icon="@mipmap/launcher_icon">
<activity
Expand Down
21 changes: 21 additions & 0 deletions ios/Runner/GeneratedPluginRegistrant.m
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,36 @@

#import "GeneratedPluginRegistrant.h"

#if __has_include(<file_saver/FileSaverPlugin.h>)
#import <file_saver/FileSaverPlugin.h>
#else
@import file_saver;
#endif

#if __has_include(<flutter_native_splash/FlutterNativeSplashPlugin.h>)
#import <flutter_native_splash/FlutterNativeSplashPlugin.h>
#else
@import flutter_native_splash;
#endif

#if __has_include(<image_picker_ios/FLTImagePickerPlugin.h>)
#import <image_picker_ios/FLTImagePickerPlugin.h>
#else
@import image_picker_ios;
#endif

#if __has_include(<path_provider_foundation/PathProviderPlugin.h>)
#import <path_provider_foundation/PathProviderPlugin.h>
#else
@import path_provider_foundation;
#endif

#if __has_include(<share_plus/FPPSharePlusPlugin.h>)
#import <share_plus/FPPSharePlusPlugin.h>
#else
@import share_plus;
#endif

#if __has_include(<shared_preferences_foundation/SharedPreferencesPlugin.h>)
#import <shared_preferences_foundation/SharedPreferencesPlugin.h>
#else
Expand All @@ -33,8 +51,11 @@
@implementation GeneratedPluginRegistrant

+ (void)registerWithRegistry:(NSObject<FlutterPluginRegistry>*)registry {
[FileSaverPlugin registerWithRegistrar:[registry registrarForPlugin:@"FileSaverPlugin"]];
[FlutterNativeSplashPlugin registerWithRegistrar:[registry registrarForPlugin:@"FlutterNativeSplashPlugin"]];
[FLTImagePickerPlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTImagePickerPlugin"]];
[PathProviderPlugin registerWithRegistrar:[registry registrarForPlugin:@"PathProviderPlugin"]];
[FPPSharePlusPlugin registerWithRegistrar:[registry registrarForPlugin:@"FPPSharePlusPlugin"]];
[SharedPreferencesPlugin registerWithRegistrar:[registry registrarForPlugin:@"SharedPreferencesPlugin"]];
[SqflitePlugin registerWithRegistrar:[registry registrarForPlugin:@"SqflitePlugin"]];
}
Expand Down
112 changes: 110 additions & 2 deletions lib/src/magic_toolbox/magic_toolbox.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
import 'dart:typed_data';
import 'package:file_saver/file_saver.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:image_picker/image_picker.dart';
import 'package:sane_gallery/src/widgets/fancy_elevated_button.dart';
import 'package:sane_gallery/src/widgets/instax_card.dart';
import 'package:sane_gallery/src/widgets/mobile_only_widget.dart';
import 'package:sane_gallery/src/widgets/sane_padding.dart';
import 'package:share_plus/share_plus.dart';
import 'package:widgets_to_image/widgets_to_image.dart';

class MagicToolbox extends StatefulWidget {
static const pathName = '/magic-toolbox';
Expand All @@ -10,12 +20,110 @@ class MagicToolbox extends StatefulWidget {
}

class _MagicToolboxState extends State<MagicToolbox> {
Future<Uint8List>? _imageBytes;
final widgetsToImageController = WidgetsToImageController();

@override
Widget build(BuildContext context) {
return const SafeArea(
return SafeArea(
child: Scaffold(
body: Center(child: Text('Magic Toolbox')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.only(bottom: 16.0),
child: FancyElevatedButton(
label: const Text(
'Instax Printer...!',
style: TextStyle(fontStyle: FontStyle.italic),
),
onPressed: () async {
final ImagePicker picker = ImagePicker();
final image =
await picker.pickImage(source: ImageSource.gallery);

if (image != null) {
setState(() {
_imageBytes = image.readAsBytes();
});
}
},
icon: const Padding(
padding: EdgeInsets.all(8.0),
child: Icon(Icons.add_a_photo),
),
),
),
if (_imageBytes != null)
FutureBuilder(
future: _imageBytes,
builder: (context, snapshot) {
if (snapshot.hasData) {
final bytes = snapshot.data as Uint8List;

return Column(
children: [
WidgetsToImage(
controller: widgetsToImageController,
child: SizedBox(
width: 300,
height: 300,
child:
InstaxCard(imageProvider: MemoryImage(bytes)),
),
),
SanePadding(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton.outlined(
onPressed: _saveInstaxPng,
icon: const Icon(Icons.download_sharp),
),
const SizedBox(width: 16),
MobileOnlyWidget(
child: IconButton.outlined(
icon: const Icon(Icons.share),
onPressed: () async {
final bytes = await widgetsToImageController
.capture();

Share.shareXFiles([
XFile.fromData(
bytes!,
name:
'saneGallery ${DateTime.now().toIso8601String()}.png',
mimeType: 'image/png',
),
]);
},
)),
],
),
),
],
);
} else {
return const CircularProgressIndicator();
}
})
],
)),
),
);
}

void _saveInstaxPng() async {
final bytes = await widgetsToImageController.capture();

final res = await FileSaver.instance.saveFile(
name: 'saneGallery ${DateTime.now().toIso8601String()}',
bytes: bytes!,
mimeType: MimeType.png,
ext: 'png',
);

print(res);
}
}
36 changes: 9 additions & 27 deletions lib/src/settings/settings_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:go_router/go_router.dart';
import 'package:sane_gallery/src/magic_toolbox/magic_toolbox.dart';

import 'package:sane_gallery/src/settings/settings_controller.dart';
import 'package:sane_gallery/src/widgets/fancy_elevated_button.dart';
import 'package:sane_gallery/src/widgets/sane_padding.dart';
import 'package:sane_gallery/src/widgets/toggle_theme_buttons.dart';

Expand Down Expand Up @@ -72,36 +73,17 @@ class SettingsView extends StatelessWidget {
),
SanePadding(
child: UnconstrainedBox(
child: ElevatedButton(
style: ButtonStyle(
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(0),
topRight: Radius.circular(8.0),
bottomLeft: Radius.circular(8.0),
bottomRight: Radius.circular(0),
),
),
),
),
child: FancyElevatedButton(
label: const Text('Magic Toolbox'),
onPressed: () {
context.go(MagicToolbox.pathName);
},
child: Padding(
padding: const EdgeInsets.only(top: 12, bottom: 12),
child: Wrap(
crossAxisAlignment: WrapCrossAlignment.center,
spacing: 8,
children: [
const Text('Magic Toolbox'),
SvgPicture.asset('assets/svg/magic-wand.svg',
width: 16,
height: 16,
colorFilter: ColorFilter.mode(
Theme.of(context).primaryColor, BlendMode.srcIn)),
],
),
icon: SvgPicture.asset(
'assets/svg/magic-wand.svg',
width: 24,
height: 24,
colorFilter: ColorFilter.mode(
Theme.of(context).primaryColor, BlendMode.srcIn),
),
),
)),
Expand Down
3 changes: 3 additions & 0 deletions lib/src/shared/platform_checks.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import 'dart:io';

final bool isMobile = Platform.isAndroid || Platform.isIOS;
41 changes: 41 additions & 0 deletions lib/src/widgets/fancy_elevated_button.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import 'package:flutter/material.dart';

class FancyElevatedButton extends StatelessWidget {
final void Function()? onPressed;
final Widget? icon;
final Widget? label;

const FancyElevatedButton({
super.key,
required this.onPressed,
required this.icon,
required this.label,
});

@override
Widget build(BuildContext context) {
return ElevatedButton.icon(
onPressed: onPressed,
label: Padding(
padding: const EdgeInsets.only(top: 12, bottom: 12, left: 8),
child: label,
),
icon: Padding(
padding: const EdgeInsets.only(left: 8.0),
child: icon,
),
style: ButtonStyle(
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(0),
topRight: Radius.circular(8.0),
bottomLeft: Radius.circular(8.0),
bottomRight: Radius.circular(0),
),
),
),
),
);
}
}
14 changes: 13 additions & 1 deletion lib/src/widgets/instax_card.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class InstaxCard extends StatelessWidget {
return Align(
alignment: Alignment.center,
child: RotatedBox(
// TODO: calculate quarterTurns based on image orientation
// FIXME: calculate quarterTurns based on image orientation
quarterTurns: 0,
child: AspectRatio(
aspectRatio: 2.1 / 3.4,
Expand All @@ -36,6 +36,18 @@ class InstaxCard extends StatelessWidget {
aspectRatio: 1.8 / 2.4,
child: Container(
decoration: BoxDecoration(
border: Border.all(
color: Theme.of(context).shadowColor.withAlpha(25),
width: 1,
),
boxShadow: [
BoxShadow(
color: Theme.of(context).shadowColor.withAlpha(125),
blurRadius: 4,
spreadRadius: -4,
offset: const Offset(0, 4),
),
],
image: DecorationImage(
image: imageProvider,
fit: BoxFit.cover,
Expand Down
13 changes: 13 additions & 0 deletions lib/src/widgets/mobile_only_widget.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import 'package:flutter/material.dart';
import 'package:sane_gallery/src/shared/platform_checks.dart';

class MobileOnlyWidget extends StatelessWidget {
final Widget child;

const MobileOnlyWidget({super.key, required this.child});

@override
Widget build(BuildContext context) {
return isMobile ? child : const SizedBox.shrink();
}
}
12 changes: 12 additions & 0 deletions linux/flutter/generated_plugin_registrant.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,18 @@

#include "generated_plugin_registrant.h"

#include <file_saver/file_saver_plugin.h>
#include <file_selector_linux/file_selector_plugin.h>
#include <url_launcher_linux/url_launcher_plugin.h>

void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) file_saver_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "FileSaverPlugin");
file_saver_plugin_register_with_registrar(file_saver_registrar);
g_autoptr(FlPluginRegistrar) file_selector_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin");
file_selector_plugin_register_with_registrar(file_selector_linux_registrar);
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);
}
3 changes: 3 additions & 0 deletions linux/flutter/generated_plugins.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
#

list(APPEND FLUTTER_PLUGIN_LIST
file_saver
file_selector_linux
url_launcher_linux
)

list(APPEND FLUTTER_FFI_PLUGIN_LIST
Expand Down
6 changes: 6 additions & 0 deletions macos/Flutter/GeneratedPluginRegistrant.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,18 @@
import FlutterMacOS
import Foundation

import file_saver
import file_selector_macos
import path_provider_foundation
import share_plus
import shared_preferences_foundation
import sqflite

func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
FileSaverPlugin.register(with: registry.registrar(forPlugin: "FileSaverPlugin"))
FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin"))
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
}
Loading
Loading