Merge branch 'master' into dev

This commit is contained in:
Kingkor Roy Tirtho 2023-08-26 10:52:37 +06:00
commit dbf6748ddc
16 changed files with 131 additions and 57 deletions

View File

@ -25,6 +25,7 @@ All types of contributions are encouraged and valued. See the [Table of Contents
- [Before Submitting an Enhancement](#before-submitting-an-enhancement) - [Before Submitting an Enhancement](#before-submitting-an-enhancement)
- [How Do I Submit a Good Enhancement Suggestion?](#how-do-i-submit-a-good-enhancement-suggestion) - [How Do I Submit a Good Enhancement Suggestion?](#how-do-i-submit-a-good-enhancement-suggestion)
- [Your First Code Contribution](#your-first-code-contribution) - [Your First Code Contribution](#your-first-code-contribution)
- [Submit translations](#submit-translations)
## Code of Conduct ## Code of Conduct
@ -122,16 +123,16 @@ Do the following:
- Install Development dependencies in linux - Install Development dependencies in linux
- Debian (>=12/Bookworm)/Ubuntu - Debian (>=12/Bookworm)/Ubuntu
```bash ```bash
$ apt-get install mpv libmpv-dev libappindicator3-1 gir1.2-appindicator3-0.1 libappindicator3-dev libsecret-1-0 libjsoncpp25 libsecret-1-dev libjsoncpp-dev libnotify-bin libnotify-dev network-manager $ apt-get install mpv libmpv-dev libappindicator3-1 gir1.2-appindicator3-0.1 libappindicator3-dev libsecret-1-0 libjsoncpp25 libsecret-1-dev libjsoncpp-dev libnotify-bin libnotify-dev
``` ```
- Use `libjsoncpp1` instead of `libjsoncpp25` (for Ubuntu < 22.04) - Use `libjsoncpp1` instead of `libjsoncpp25` (for Ubuntu < 22.04)
- Arch/Manjaro - Arch/Manjaro
```bash ```bash
yay -S mpv libappindicator-gtk3 libsecret jsoncpp libnotify networkmanager yay -S mpv libappindicator-gtk3 libsecret jsoncpp libnotify
``` ```
- Fedora - Fedora
```bash ```bash
dnf install mpv mpv-devel libappindicator-gtk3 libappindicator-gtk3-devel libsecret libsecret-devel jsoncpp jsoncpp-devel libnotify libnotify-devel NetworkManager dnf install mpv mpv-devel libappindicator-gtk3 libappindicator-gtk3-devel libsecret libsecret-devel jsoncpp jsoncpp-devel libnotify libnotify-devel
``` ```
- Clone the Repo - Clone the Repo
- Create a `.env` in root of the project following the `.env.example` template - Create a `.env` in root of the project following the `.env.example` template
@ -145,3 +146,21 @@ Do the following:
``` ```
Do debugging/testing/build etc then submit to us with PR against the development branch (master) & we'll review your code Do debugging/testing/build etc then submit to us with PR against the development branch (master) & we'll review your code
### Submit Translations
Make sure you're familiar with [Flutter localization](https://docs.flutter.dev/ui/accessibility-and-localization/internationalization). Then, you can start translating the app by following these steps:
- Do all the steps in [Your First Code Contribution](#your-first-code-contribution)
- Make sure application starts in debug mode
- Now, in `lib/l10n/app_<2-letter code of your language>.arb` (create if not exists) add necessary translations
> (You can follow the `lib/l10n/app_en.arb` for reference)
- If you're adding missing translations, you can check the `/untranslated_messages.json` file to see which messages are missing in your native locale
- If you added entirely new translations:
- Add `const Locale('<2-letter language code>', '<2-letter ISO country code>')` in `lib/l10n/l10n.dart`'s `static final all = [...]` variable
- Uncomment the Map entry of your locale from `lib/collections/language_codes.dart`'s `static final Map isoLangs = {` variable
- Now restart (hot restart if running already) the app in debug mode & go to "Settings" > "Language" & see if your locale shows up
- If it does, select it & see if the app is translated properly
- Now git commit the changes & push
- Finally, submit a PR against the development branch (dev) & we'll review your code

View File

@ -10,7 +10,6 @@ pkgbase = spotube-bin
depends = libsecret depends = libsecret
depends = jsoncpp depends = jsoncpp
depends = libnotify depends = libnotify
depends = networkmanager
source = https://github.com/KRTirtho/spotube/releases/download/v2.3.0/Spotube-linux-x86_64.tar.xz source = https://github.com/KRTirtho/spotube/releases/download/v2.3.0/Spotube-linux-x86_64.tar.xz
md5sums = 8cd6a7385c5c75d203dccd762f1d63ec md5sums = 8cd6a7385c5c75d203dccd762f1d63ec

View File

@ -8,7 +8,7 @@ arch=(x86_64)
url="https://github.com/KRTirtho/spotube/" url="https://github.com/KRTirtho/spotube/"
license=('BSD-4-Clause') license=('BSD-4-Clause')
groups=() groups=()
depends=('mpv' 'libappindicator-gtk3' 'libsecret' 'jsoncpp' 'libnotify' 'networkmanager') depends=('mpv' 'libappindicator-gtk3' 'libsecret' 'jsoncpp' 'libnotify')
makedepends=() makedepends=()
checkdepends=() checkdepends=()
optdepends=() optdepends=()

View File

@ -91,4 +91,6 @@ abstract class SpotubeIcons {
static const clipboard = FeatherIcons.clipboard; static const clipboard = FeatherIcons.clipboard;
static const api = FeatherIcons.database; static const api = FeatherIcons.database;
static const skip = FeatherIcons.fastForward; static const skip = FeatherIcons.fastForward;
static const noWifi = FeatherIcons.wifiOff;
static const wifi = FeatherIcons.wifi;
} }

View File

@ -256,5 +256,7 @@
"encryption_failed_warning": "Spotube uses encryption to securely store your data. But failed to do so. So it'll fallback to insecure storage\nIf you're using linux, please make sure you've any secret-service (gnome-keyring, kde-wallet, keepassxc etc) installed", "encryption_failed_warning": "Spotube uses encryption to securely store your data. But failed to do so. So it'll fallback to insecure storage\nIf you're using linux, please make sure you've any secret-service (gnome-keyring, kde-wallet, keepassxc etc) installed",
"querying_info": "Querying info...", "querying_info": "Querying info...",
"piped_api_down": "Piped API is down", "piped_api_down": "Piped API is down",
"piped_down_error_instructions": "The Piped instance {pipedInstance} is currently down\n\nEither change the instance or change the 'API type' to official YouTube API\n\nMake sure to restart the app after change" "piped_down_error_instructions": "The Piped instance {pipedInstance} is currently down\n\nEither change the instance or change the 'API type' to official YouTube API\n\nMake sure to restart the app after change",
"you_are_offline": "You are currently offline",
"connection_restored": "Your internet connection was restored"
} }

View File

@ -4,7 +4,6 @@ import 'package:args/args.dart';
import 'package:catcher/catcher.dart'; import 'package:catcher/catcher.dart';
import 'package:device_preview/device_preview.dart'; import 'package:device_preview/device_preview.dart';
import 'package:fl_query/fl_query.dart'; import 'package:fl_query/fl_query.dart';
import 'package:fl_query_connectivity_plus_adapter/fl_query_connectivity_plus_adapter.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
@ -27,6 +26,7 @@ import 'package:spotube/models/skip_segment.dart';
import 'package:spotube/provider/palette_provider.dart'; import 'package:spotube/provider/palette_provider.dart';
import 'package:spotube/provider/user_preferences_provider.dart'; import 'package:spotube/provider/user_preferences_provider.dart';
import 'package:spotube/services/audio_player/audio_player.dart'; import 'package:spotube/services/audio_player/audio_player.dart';
import 'package:spotube/services/connectivity_adapter.dart';
import 'package:spotube/themes/theme.dart'; import 'package:spotube/themes/theme.dart';
import 'package:spotube/utils/persisted_state_notifier.dart'; import 'package:spotube/utils/persisted_state_notifier.dart';
import 'package:system_theme/system_theme.dart'; import 'package:system_theme/system_theme.dart';
@ -105,7 +105,7 @@ Future<void> main(List<String> rawArgs) async {
await QueryClient.initialize( await QueryClient.initialize(
cachePrefix: "oss.krtirtho.spotube", cachePrefix: "oss.krtirtho.spotube",
cacheDir: hiveCacheDir, cacheDir: hiveCacheDir,
connectivity: FlQueryConnectivityPlusAdapter(), connectivity: FlQueryInternetConnectionCheckerAdapter(),
); );
Hive.registerAdapter(MatchedTrackAdapter()); Hive.registerAdapter(MatchedTrackAdapter());
Hive.registerAdapter(SkipSegmentAdapter()); Hive.registerAdapter(SkipSegmentAdapter());

View File

@ -5,11 +5,14 @@ import 'package:flutter/services.dart';
import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:internet_connection_checker/internet_connection_checker.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'package:spotube/collections/spotube_icons.dart';
import 'package:spotube/components/shared/dialogs/replace_downloaded_dialog.dart'; import 'package:spotube/components/shared/dialogs/replace_downloaded_dialog.dart';
import 'package:spotube/components/root/bottom_player.dart'; import 'package:spotube/components/root/bottom_player.dart';
import 'package:spotube/components/root/sidebar.dart'; import 'package:spotube/components/root/sidebar.dart';
import 'package:spotube/components/root/spotube_navigation_bar.dart'; import 'package:spotube/components/root/spotube_navigation_bar.dart';
import 'package:spotube/extensions/context.dart';
import 'package:spotube/hooks/use_update_checker.dart'; import 'package:spotube/hooks/use_update_checker.dart';
import 'package:spotube/provider/download_manager_provider.dart'; import 'package:spotube/provider/download_manager_provider.dart';
import 'package:spotube/utils/persisted_state_notifier.dart'; import 'package:spotube/utils/persisted_state_notifier.dart';
@ -34,6 +37,8 @@ class RootApp extends HookConsumerWidget {
final isMounted = useIsMounted(); final isMounted = useIsMounted();
final showingDialogCompleter = useRef(Completer()..complete()); final showingDialogCompleter = useRef(Completer()..complete());
final downloader = ref.watch(downloadManagerProvider); final downloader = ref.watch(downloadManagerProvider);
final scaffoldMessenger = ScaffoldMessenger.of(context);
final theme = Theme.of(context);
useEffect(() { useEffect(() {
WidgetsBinding.instance.addPostFrameCallback((_) async { WidgetsBinding.instance.addPostFrameCallback((_) async {
@ -44,6 +49,52 @@ class RootApp extends HookConsumerWidget {
await PersistedStateNotifier.showNoEncryptionDialog(context); await PersistedStateNotifier.showNoEncryptionDialog(context);
} }
}); });
final subscription =
InternetConnectionChecker().onStatusChange.listen((status) {
switch (status) {
case InternetConnectionStatus.connected:
scaffoldMessenger.showSnackBar(
SnackBar(
content: Row(
children: [
Icon(
SpotubeIcons.wifi,
color: theme.colorScheme.onPrimary,
),
const SizedBox(width: 10),
Text(context.l10n.connection_restored),
],
),
backgroundColor: theme.colorScheme.primary,
showCloseIcon: true,
width: 350,
),
);
case InternetConnectionStatus.disconnected:
scaffoldMessenger.showSnackBar(
SnackBar(
content: Row(
children: [
Icon(
SpotubeIcons.noWifi,
color: theme.colorScheme.onError,
),
const SizedBox(width: 10),
Text(context.l10n.you_are_offline),
],
),
backgroundColor: theme.colorScheme.error,
showCloseIcon: true,
width: 300,
),
);
}
});
return () {
subscription.cancel();
};
}, []); }, []);
useEffect(() { useEffect(() {

View File

@ -0,0 +1,12 @@
import 'package:fl_query/fl_query.dart';
import 'package:internet_connection_checker/internet_connection_checker.dart';
class FlQueryInternetConnectionCheckerAdapter extends ConnectivityAdapter {
@override
Future<bool> get isConnected => InternetConnectionChecker().hasConnection;
@override
Stream<bool> get onConnectivityChanged => InternetConnectionChecker()
.onStatusChange
.map((status) => status == InternetConnectionStatus.connected);
}

View File

@ -16,7 +16,6 @@ dependencies:
- libsecret-1-0 - libsecret-1-0
- libnotify-bin - libnotify-bin
- libjsoncpp25 - libjsoncpp25
- network-manager
essential: false essential: false
icon: assets/spotube-logo.png icon: assets/spotube-logo.png

View File

@ -12,7 +12,6 @@ requires:
- jsoncpp - jsoncpp
- libsecret - libsecret
- libnotify - libnotify
- NetworkManager
display_name: Spotube display_name: Spotube

View File

@ -8,7 +8,6 @@ import Foundation
import audio_service import audio_service
import audio_session import audio_session
import catcher import catcher
import connectivity_plus
import device_info_plus import device_info_plus
import flutter_secure_storage_macos import flutter_secure_storage_macos
import local_notifier import local_notifier
@ -28,7 +27,6 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
AudioServicePlugin.register(with: registry.registrar(forPlugin: "AudioServicePlugin")) AudioServicePlugin.register(with: registry.registrar(forPlugin: "AudioServicePlugin"))
AudioSessionPlugin.register(with: registry.registrar(forPlugin: "AudioSessionPlugin")) AudioSessionPlugin.register(with: registry.registrar(forPlugin: "AudioSessionPlugin"))
CatcherPlugin.register(with: registry.registrar(forPlugin: "CatcherPlugin")) CatcherPlugin.register(with: registry.registrar(forPlugin: "CatcherPlugin"))
ConnectivityPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlugin"))
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin")) FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin"))
LocalNotifierPlugin.register(with: registry.registrar(forPlugin: "LocalNotifierPlugin")) LocalNotifierPlugin.register(with: registry.registrar(forPlugin: "LocalNotifierPlugin"))

View File

@ -330,22 +330,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.0" version: "3.0.0"
connectivity_plus:
dependency: transitive
description:
name: connectivity_plus
sha256: "8599ae9edca5ff96163fca3e36f8e481ea917d1e71cdad912c084b5579913f34"
url: "https://pub.dev"
source: hosted
version: "4.0.1"
connectivity_plus_platform_interface:
dependency: transitive
description:
name: connectivity_plus_platform_interface
sha256: cf1d1c28f4416f8c654d7dc3cd638ec586076255d407cef3ddbdaf178272a71a
url: "https://pub.dev"
source: hosted
version: "1.2.4"
convert: convert:
dependency: transitive dependency: transitive
description: description:
@ -538,14 +522,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.0-alpha.3" version: "1.0.0-alpha.3"
fl_query_connectivity_plus_adapter:
dependency: "direct main"
description:
name: fl_query_connectivity_plus_adapter
sha256: a0e69615e25f6dfe74d1e5a0909aeeb865e93c65dd4e0b236f0846f9e54f758b
url: "https://pub.dev"
source: hosted
version: "0.1.0-alpha.2"
fl_query_hooks: fl_query_hooks:
dependency: "direct main" dependency: "direct main"
description: description:
@ -966,6 +942,14 @@ packages:
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.0" version: "0.0.0"
internet_connection_checker:
dependency: "direct main"
description:
name: internet_connection_checker
sha256: "1c683e63e89c9ac66a40748b1b20889fd9804980da732bf2b58d6d5456c8e876"
url: "https://pub.dev"
source: hosted
version: "1.0.0+1"
intl: intl:
dependency: "direct main" dependency: "direct main"
description: description:
@ -1174,14 +1158,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.0" version: "1.0.0"
nm:
dependency: transitive
description:
name: nm
sha256: "2c9aae4127bdc8993206464fcc063611e0e36e72018696cd9631023a31b24254"
url: "https://pub.dev"
source: hosted
version: "0.5.0"
oauth2: oauth2:
dependency: transitive dependency: transitive
description: description:

View File

@ -36,7 +36,6 @@ dependencies:
file_picker: ^5.2.2 file_picker: ^5.2.2
fl_query: ^1.0.0-alpha.3 fl_query: ^1.0.0-alpha.3
fl_query_hooks: ^1.0.0-alpha.3 fl_query_hooks: ^1.0.0-alpha.3
fl_query_connectivity_plus_adapter: ^0.1.0-alpha.2
fluentui_system_icons: ^1.1.189 fluentui_system_icons: ^1.1.189
flutter: flutter:
sdk: flutter sdk: flutter
@ -63,6 +62,7 @@ dependencies:
hooks_riverpod: ^2.1.1 hooks_riverpod: ^2.1.1
html: ^0.15.1 html: ^0.15.1
http: ^1.1.0 http: ^1.1.0
internet_connection_checker: ^1.0.0+1
intl: ^0.18.0 intl: ^0.18.0
introduction_screen: ^3.0.2 introduction_screen: ^3.0.2
json_annotation: ^4.8.1 json_annotation: ^4.8.1

View File

@ -1,42 +1,63 @@
{ {
"bn": [ "bn": [
"piped_api_down", "piped_api_down",
"piped_down_error_instructions" "piped_down_error_instructions",
"you_are_offline",
"connection_restored"
], ],
"ca": [ "ca": [
"querying_info", "querying_info",
"piped_api_down", "piped_api_down",
"piped_down_error_instructions" "piped_down_error_instructions",
"you_are_offline",
"connection_restored"
], ],
"de": [ "de": [
"piped_api_down", "piped_api_down",
"piped_down_error_instructions" "piped_down_error_instructions",
"you_are_offline",
"connection_restored"
], ],
"es": [ "es": [
"piped_api_down", "piped_api_down",
"piped_down_error_instructions" "piped_down_error_instructions",
"you_are_offline",
"connection_restored"
], ],
"fr": [ "fr": [
"piped_api_down", "piped_api_down",
"piped_down_error_instructions" "piped_down_error_instructions",
"you_are_offline",
"connection_restored"
], ],
"hi": [ "hi": [
"piped_api_down", "piped_api_down",
"piped_down_error_instructions" "piped_down_error_instructions",
"you_are_offline",
"connection_restored"
], ],
"ja": [ "ja": [
"piped_api_down", "piped_api_down",
"piped_down_error_instructions" "piped_down_error_instructions",
"you_are_offline",
"connection_restored"
],
"pl": [
"you_are_offline",
"connection_restored"
], ],
"zh": [ "zh": [
"piped_api_down", "piped_api_down",
"piped_down_error_instructions" "piped_down_error_instructions",
"you_are_offline",
"connection_restored"
] ]
} }

View File

@ -7,7 +7,6 @@
#include "generated_plugin_registrant.h" #include "generated_plugin_registrant.h"
#include <catcher/catcher_plugin.h> #include <catcher/catcher_plugin.h>
#include <connectivity_plus/connectivity_plus_windows_plugin.h>
#include <flutter_secure_storage_windows/flutter_secure_storage_windows_plugin.h> #include <flutter_secure_storage_windows/flutter_secure_storage_windows_plugin.h>
#include <local_notifier/local_notifier_plugin.h> #include <local_notifier/local_notifier_plugin.h>
#include <media_kit_libs_windows_audio/media_kit_libs_windows_audio_plugin_c_api.h> #include <media_kit_libs_windows_audio/media_kit_libs_windows_audio_plugin_c_api.h>
@ -22,8 +21,6 @@
void RegisterPlugins(flutter::PluginRegistry* registry) { void RegisterPlugins(flutter::PluginRegistry* registry) {
CatcherPluginRegisterWithRegistrar( CatcherPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("CatcherPlugin")); registry->GetRegistrarForPlugin("CatcherPlugin"));
ConnectivityPlusWindowsPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("ConnectivityPlusWindowsPlugin"));
FlutterSecureStorageWindowsPluginRegisterWithRegistrar( FlutterSecureStorageWindowsPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin")); registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin"));
LocalNotifierPluginRegisterWithRegistrar( LocalNotifierPluginRegisterWithRegistrar(

View File

@ -4,7 +4,6 @@
list(APPEND FLUTTER_PLUGIN_LIST list(APPEND FLUTTER_PLUGIN_LIST
catcher catcher
connectivity_plus
flutter_secure_storage_windows flutter_secure_storage_windows
local_notifier local_notifier
media_kit_libs_windows_audio media_kit_libs_windows_audio