diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 00000000..55fee41a
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,4 @@
+build
+dist
+.dart_tool
+.idea
diff --git a/.fvm/fvm_config.json b/.fvm/fvm_config.json
index 7ca74200..d42a42fa 100644
--- a/.fvm/fvm_config.json
+++ b/.fvm/fvm_config.json
@@ -1,4 +1,4 @@
{
- "flutterSdkVersion": "3.19.1",
+ "flutterSdkVersion": "3.19.5",
"flavors": {}
}
\ No newline at end of file
diff --git a/.github/Dockerfile b/.github/Dockerfile
new file mode 100644
index 00000000..e4dacb0e
--- /dev/null
+++ b/.github/Dockerfile
@@ -0,0 +1,32 @@
+ARG FLUTTER_VERSION
+ARG BUILD_VERSION
+
+FROM --platform=arm64 fischerscode/flutter-sudo:${FLUTTER_VERSION}
+
+WORKDIR /app
+
+# Install dependencies
+RUN sudo apt-get update &&\
+ sudo apt-get install -y tar clang cmake ninja-build pkg-config libgtk-3-dev make python3-pip python3-setuptools desktop-file-utils libgdk-pixbuf2.0-dev fakeroot strace fuse libunwind-dev locate patchelf gir1.2-appindicator3-0.1 libappindicator3-1 libappindicator3-dev libsecret-1-0 libjsoncpp25 libsecret-1-dev libjsoncpp-dev libnotify-bin libnotify-dev mpv libmpv-dev rpm &&\
+ sudo rm -rf /var/lib/apt/lists/*
+
+COPY . .
+
+RUN sudo chown -R $(whoami) /app
+
+RUN flutter pub get &&\
+ flutter config --enable-linux-desktop &&\
+ flutter pub get &&\
+ dart run build_runner build --delete-conflicting-outputs
+
+RUN dart pub global activate flutter_distributor &&\
+ alias dpkg-deb="dpkg-deb --Zxz" &&\
+ flutter_distributor package --platform=linux --targets=deb &&\
+ flutter_distributor package --platform=linux --targets=rpm
+
+
+RUN make tar VERSION=${BUILD_VERSION} ARCH=arm64 PKG_ARCH=aarch64
+
+RUN mv build/spotube-linux-*-aarch64.tar.xz dist/ &&\
+ mv dist/**/spotube-*-linux.deb dist/Spotube-linux-aarch64.deb &&\
+ mv dist/**/spotube-*-linux.rpm dist/Spotube-linux-aarch64.rpm
\ No newline at end of file
diff --git a/.github/workflows/spotube-publish-binary.yml b/.github/workflows/spotube-publish-binary.yml
index 805a89ac..960507f9 100644
--- a/.github/workflows/spotube-publish-binary.yml
+++ b/.github/workflows/spotube-publish-binary.yml
@@ -4,7 +4,7 @@ on:
inputs:
version:
description: Version to publish (x.x.x)
- default: 3.1.0
+ default: 3.6.0
required: true
dry_run:
description: Dry run
diff --git a/.github/workflows/spotube-release-binary.yml b/.github/workflows/spotube-release-binary.yml
index 5d918a03..c7753155 100644
--- a/.github/workflows/spotube-release-binary.yml
+++ b/.github/workflows/spotube-release-binary.yml
@@ -4,7 +4,7 @@ on:
inputs:
version:
description: Version to release (x.x.x)
- default: 3.4.1
+ default: 3.6.0
required: true
channel:
type: choice
@@ -26,7 +26,7 @@ on:
default: true
env:
- FLUTTER_VERSION: '3.19.1'
+ FLUTTER_VERSION: '3.19.5'
jobs:
windows:
@@ -70,7 +70,7 @@ jobs:
run: |
flutter config --enable-windows-desktop
flutter pub get
- dart run build_runner build --delete-conflicting-outputs --enable-experiment=records,patterns
+ dart run build_runner build --delete-conflicting-outputs
- name: Build Windows Executable
run: |
@@ -156,7 +156,7 @@ jobs:
run: |
flutter config --enable-linux-desktop
flutter pub get
- dart run build_runner build --delete-conflicting-outputs --enable-experiment=records,patterns
+ dart run build_runner build --delete-conflicting-outputs
- name: Build Linux Packages
run: |
@@ -206,6 +206,66 @@ jobs:
with:
limit-access-to-actor: true
+ linux_arm:
+ runs-on: macos-14
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Install Docker
+ run: brew install --cask docker
+
+ - name: Replace pubspec version and BUILD_VERSION Env (nightly)
+ if: ${{ inputs.channel == 'nightly' }}
+ run: |
+ brew install yq
+ yq -i '.version |= sub("\+\d+", "+${{ inputs.channel }}.")' pubspec.yaml
+ yq -i '.version += strenv(GITHUB_RUN_NUMBER)' pubspec.yaml
+ echo "BUILD_VERSION=${{ inputs.version }}+${{ inputs.channel }}.${{ github.run_number }}" >> $GITHUB_ENV
+
+
+ - name: BUILD_VERSION Env (stable)
+ if: ${{ inputs.channel == 'stable' }}
+ run: |
+ echo "BUILD_VERSION=${{ inputs.version }}" >> $GITHUB_ENV
+
+ - name: Get current date
+ id: date
+ run: echo "::set-output name=date::$(date +'%Y-%m-%d')"
+
+ - name: Replace Version in files
+ run: |
+ sed -i '' 's|%{{APPDATA_RELEASE}}%||' linux/com.github.KRTirtho.Spotube.appdata.xml
+
+ - name: Create Stable .env
+ if: ${{ inputs.channel == 'stable' }}
+ run: echo '${{ secrets.DOTENV_RELEASE }}' > .env
+
+ - name: Create Nightly .env
+ if: ${{ inputs.channel == 'nightly' }}
+ run: echo '${{ secrets.DOTENV_NIGHTLY }}' > .env
+
+ - name: Build Linux Arm
+ run: |
+ docker build -t spotube-linux-arm -f .github/Dockerfile . --build-arg BUILD_VERSION=${{ env.BUILD_VERSION }} --build-arg FLUTTER_VERSION=${{ env.FLUTTER_VERSION }}
+ docker create --name spotube-linux-arm spotube-linux-arm
+ docker cp spotube-linux-arm:/app/dist .
+ docker rm -f spotube-linux-arm
+
+ - uses: actions/upload-artifact@v3
+ with:
+ if-no-files-found: error
+ name: Spotube-Release-Binaries
+ path: |
+ dist/Spotube-linux-aarch64.deb
+ dist/Spotube-linux-aarch64.rpm
+ dist/spotube-linux-nightly-aarch64.tar.xz
+
+ - name: Debug With SSH When fails
+ if: ${{ failure() && inputs.debug && inputs.channel == 'nightly' }}
+ uses: mxschmitt/action-tmate@v3
+ with:
+ limit-access-to-actor: true
+
android:
runs-on: ubuntu-latest
@@ -245,7 +305,7 @@ jobs:
- name: Generate Secrets
run: |
flutter pub get
- dart run build_runner build --delete-conflicting-outputs --enable-experiment=records,patterns
+ dart run build_runner build --delete-conflicting-outputs
- name: Sign Apk
run: |
@@ -260,7 +320,7 @@ jobs:
- name: Build Playstore AppBundle
run: |
echo 'ENABLE_UPDATE_CHECK=0' >> .env
- dart run build_runner build --delete-conflicting-outputs --enable-experiment=records,patterns
+ dart run build_runner build --delete-conflicting-outputs
export MANIFEST=android/app/src/main/AndroidManifest.xml
xmlstarlet ed -d '//meta-data[@android:name="com.google.android.gms.car.application"]' $MANIFEST > $MANIFEST.tmp
mv $MANIFEST.tmp $MANIFEST
@@ -283,7 +343,6 @@ jobs:
limit-access-to-actor: true
macos:
-
runs-on: macos-14
steps:
- uses: actions/checkout@v4
@@ -317,7 +376,7 @@ jobs:
run: |
dart pub global activate flutter_distributor
flutter pub get
- dart run build_runner build --delete-conflicting-outputs --enable-experiment=records,patterns
+ dart run build_runner build --delete-conflicting-outputs
- name: Build Macos App
run: |
@@ -381,7 +440,7 @@ jobs:
- name: Generate Secrets
run: |
flutter pub get
- dart run build_runner build --delete-conflicting-outputs --enable-experiment=records,patterns
+ dart run build_runner build --delete-conflicting-outputs
- name: Build iOS iPA
run: |
@@ -408,6 +467,7 @@ jobs:
needs:
- windows
- linux
+ - linux_arm
- android
- macos
- iOS
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 29c5ba4e..de5fbd69 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -24,5 +24,6 @@
"explorer.fileNesting.patterns": {
"pubspec.yaml": "pubspec.lock,analysis_options.yaml,.packages,.flutter-plugins,.flutter-plugins-dependencies,flutter_launcher_icons*.yaml,flutter_native_splash*.yaml",
"README.md": "LICENSE,CODE_OF_CONDUCT.md,CONTRIBUTING.md,SECURITY.md,CONTRIBUTION.md,CHANGELOG.md,PRIVACY_POLICY.md",
+ "*.dart": "${capture}.g.dart,${capture}.freezed.dart",
}
}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ddbd4fe1..21ca4b69 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,27 @@
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
+## [3.6.0-0](https://github.com/krtirtho/spotube/compare/v3.5.0...v3.6.0-0) (2024-04-15)
+
+
+### Features
+
+* add Spotify homepage personalized recommendations ([#1402](https://github.com/krtirtho/spotube/issues/1402)) ([9e25c74](https://github.com/krtirtho/spotube/commit/9e25c742d4e43e4e10d2b48afb8e6d90288ffa11))
+* add user profile page ([39e97ee](https://github.com/krtirtho/spotube/commit/39e97eef34d87348a264843e145f31f82832d12e))
+* **android:** Filter Device To Force High Frame Rate ([#880](https://github.com/krtirtho/spotube/issues/880)) ([6e41b10](https://github.com/krtirtho/spotube/commit/6e41b106fa989adee393d3ce2535e75446ad3eea))
+* improved caching based on riverpod ([#1343](https://github.com/krtirtho/spotube/issues/1343)) ([6673e5a](https://github.com/krtirtho/spotube/commit/6673e5a8a86b9667cf9dbff9bb7c40ea6b7de771))
+* LAN connect a.k.a control remote Spotube playback and local output device selection ([#1355](https://github.com/krtirtho/spotube/issues/1355)) ([68374ef](https://github.com/krtirtho/spotube/commit/68374efd3ec556f31b937e5b96920787b54eec78))
+* **lyrics:** add LRCLIB lyrics provider as fallback ([5afe823](https://github.com/krtirtho/spotube/commit/5afe823abdb198340b55d138d8173d886a811632))
+* search history support [#1236](https://github.com/krtirtho/spotube/issues/1236) ([82b1cfa](https://github.com/krtirtho/spotube/commit/82b1cfa0d775e3958c666280943a893c9113d468))
+* **translations:** Add Czech translation ([#1401](https://github.com/krtirtho/spotube/issues/1401)) ([5a6b800](https://github.com/krtirtho/spotube/commit/5a6b80091259359bc38c4b91cd8cb496c4270fa4))
+* **translations:** add Thai Language ([#1319](https://github.com/krtirtho/spotube/issues/1319)) ([b70f250](https://github.com/krtirtho/spotube/commit/b70f250e8d5137fd990787ec9e3d058126cf14f3)), closes [#1310](https://github.com/krtirtho/spotube/issues/1310) [#1311](https://github.com/krtirtho/spotube/issues/1311)
+
+
+### Bug Fixes
+
+* instance of Artist bug [#1362](https://github.com/krtirtho/spotube/issues/1362) ([c8dd802](https://github.com/krtirtho/spotube/commit/c8dd8025ec96bd78ed77cae35f1429aa48c16fde))
+* **playback:** sponsor block skips and stutters in same position ([0d080b7](https://github.com/krtirtho/spotube/commit/0d080b77b72529c0be5ebc27ace1c52307511f73))
+
## [3.5.0](https://github.com/krtirtho/spotube/compare/v3.4.1...v3.5.0) (2024-03-08)
diff --git a/README.md b/README.md
index 4ad4e1be..f2666fbc 100644
--- a/README.md
+++ b/README.md
@@ -97,12 +97,7 @@ This handy table lists all the methods you can use to install Spotube:
| AppImage |
-
-
-
-
- Note: AppimageLauncher is required!
- |
+ AppImage's lacking stability led to it's temporal removal. More information at https://github.com/KRTirtho/spotube/issues/1082 |
| Debian/Ubuntu |
@@ -205,6 +200,7 @@ If you are concerned, you can [read the reason of choosing this license](https:/
1. [YouTube](https://youtube.com/) - YouTube is an American online video-sharing platform headquartered in San Bruno, California. Three former PayPal employees—Chad Hurley, Steve Chen, and Jawed Karim—created the service in February 2005
1. [JioSaavn](https://www.jiosaavn.com) - JioSaavn is an Indian online music streaming service and a digital distributor of Bollywood, English and other regional Indian music across the world. Since it was founded in 2007 as Saavn, the company has acquired rights to over 5 crore (50 million) music tracks in 15 languages
1. [SongLink](https://song.link) - SongLink is a free smart link service that helps you share music with your audience. It's a one-stop-shop for creating smart links for music, podcasts, and other audio content
+1. [LRCLib](https://lrclib.net/) - A public synced lyric API
1. [Linux](https://www.linux.org) - Linux is a family of open-source Unix-like operating systems based on the Linux kernel, an operating system kernel first released on September 17, 1991, by Linus Torvalds. Linux is typically packaged in a Linux distribution
1. [AUR](https://aur.archlinux.org) - AUR stands for Arch User Repository. It is a community-driven repository for Arch-based Linux distributions users
1. [Flatpak](https://flatpak.org) - Flatpak is a utility for software deployment and package management for Linux
@@ -233,9 +229,6 @@ If you are concerned, you can [read the reason of choosing this license](https:/
1. [duration](https://github.com/desktop-dart/duration) - Utilities to make working with 'Duration's easier. Formats duration in human readable form and also parses duration in human readable form to Dart's Duration.
1. [envied](https://github.com/petercinibulk/envied) - Explicitly reads environment variables into a dart file from a .env file for more security and faster start up times.
1. [file_selector](https://pub.dev/packages/file_selector) - Flutter plugin for opening and saving files, or selecting directories, using native file selection UI.
-1. [fl_query](https://fl-query.krtirtho.dev) - Asynchronous data caching, refetching & invalidation library for Flutter
-1. [fl_query_hooks](https://fl-query.krtirtho.dev) - Elite flutter_hooks compatible library for fl_query, the Asynchronous data caching, refetching & invalidation library for Flutter
-1. [fl_query_devtools](https://fl-query.krtirtho.dev) - Devtools support for Fl-Query
1. [fluentui_system_icons](https://github.com/microsoft/fluentui-system-icons/tree/main) - Fluent UI System Icons are a collection of familiar, friendly and modern icons from Microsoft.
1. [flutter_cache_manager](https://github.com/Baseflow/flutter_cache_manager/tree/develop/flutter_cache_manager) - Generic cache manager for flutter. Saves web files on the storages of the device and saves the cache info using sqflite.
1. [flutter_displaymode](https://github.com/ajinasokan/flutter_displaymode) - A Flutter plugin to set display mode (resolution, refresh rate) on Android platform. Allows to enable high refresh rate on supported devices.
@@ -257,7 +250,7 @@ If you are concerned, you can [read the reason of choosing this license](https:/
1. [http](https://pub.dev/packages/http) - A composable, multi-platform, Future-based API for HTTP requests.
1. [image_picker](https://pub.dev/packages/image_picker) - Flutter plugin for selecting images from the Android and iOS image library, and taking new pictures with the camera.
1. [intl](https://pub.dev/packages/intl) - Contains code to deal with internationalized/localized messages, date and number formatting and parsing, bi-directional text, and other internationalization issues.
-1. [introduction_screen](https://github.com/pyozer/introduction_screen) - Introduction/Onboarding package for flutter app with some customizations possibilities
+1. [introduction_screen](https://pub.dev/packages/introduction_screen) - Introduction/Onboarding package for flutter app with some customizations possibilities
1. [json_annotation](https://pub.dev/packages/json_annotation) - Classes and helper functions that support JSON code generation via the `json_serializable` package.
1. [logger](https://pub.dev/packages/logger) - Small, easy to use and extensible logger which prints beautiful logs.
1. [media_kit](https://github.com/media-kit/media-kit) - A cross-platform video player & audio player for Flutter & Dart. Performant, stable, feature-proof & modular.
@@ -295,22 +288,32 @@ If you are concerned, you can [read the reason of choosing this license](https:/
1. [wikipedia_api](https://github.com/KRTirtho/wikipedia_api) - Wikipedia API for dart and flutter
1. [skeletonizer](https://github.com/Milad-Akarie/skeletonizer) - Converts already built widgets into skeleton loaders with no extra effort.
1. [app_links](https://github.com/llfbandit/app_links) - Android App Links, Deep Links, iOs Universal Links and Custom URL schemes handler for Flutter (desktop included).
-1. [win32_registry](https://win32.pub) - A package that provides a friendly Dart API for accessing the Windows Registry.
+1. [win32_registry](https://pub.dev/packages/win32_registry) - A package that provides a friendly Dart API for accessing the Windows Registry.
1. [flutter_sharing_intent](https://github.com/bhagat-techind/flutter_sharing_intent.git) - A flutter plugin that allow flutter apps to receive photos, videos, text, urls or any other file types from another app.
1. [flutter_broadcasts](https://pub.dev/packages/flutter_broadcasts) - A plugin for sending and receiving broadcasts with Android intents and iOS notifications.
1. [freezed_annotation](https://pub.dev/packages/freezed_annotation) - Annotations for the freezed code-generator. This package does nothing without freezed too.
1. [spotify](https://github.com/rinukkusu/spotify-dart) - An incomplete dart library for interfacing with the Spotify Web API.
+1. [bonsoir](https://bonsoir.skyost.eu) - A Zeroconf library that allows you to discover network services and to broadcast your own. Based on Apple Bonjour and Android NSD.
+1. [shelf](https://pub.dev/packages/shelf) - A model for web server middleware that encourages composition and easy reuse.
+1. [shelf_router](https://pub.dev/packages/shelf_router) - A convenient request router for the shelf web-framework, with support for URL-parameters, nested routers and routers generated from source annotations.
+1. [shelf_web_socket](https://pub.dev/packages/shelf_web_socket) - A shelf handler that wires up a listener for every connection.
+1. [web_socket_channel](https://pub.dev/packages/web_socket_channel) - StreamChannel wrappers for WebSockets. Provides a cross-platform WebSocketChannel API, a cross-platform implementation of that API that communicates over an underlying StreamChannel.
+1. [lrc](https://pub.dev/packages/lrc) - A Dart-only package that creates, parses, and handles LRC, which is a format that stores song lyrics.
+1. [pub_api_client](https://github.com/leoafarias/pub_api_client) - An API Client for Pub to interact with public package information.
+1. [pubspec_parse](https://pub.dev/packages/pubspec_parse) - Simple package for parsing pubspec.yaml files with a type-safe API and rich error reporting.
+1. [timezone](https://pub.dev/packages/timezone) - Time zone database and time zone aware DateTime.
+1. [crypto](https://pub.dev/packages/crypto) - Implementations of SHA, MD5, and HMAC cryptographic functions.
1. [build_runner](https://pub.dev/packages/build_runner) - A build system for Dart code generation and modular compilation.
1. [envied_generator](https://github.com/petercinibulk/envied) - Generator for the Envied package. See https://pub.dev/packages/envied.
-1. [flutter_distributor](https://distributor.leanflutter.org) - A complete tool for packaging and publishing your Flutter apps.
+1. [flutter_distributor](https://distributor.leanflutter.dev) - A complete tool for packaging and publishing your Flutter apps.
1. [flutter_gen_runner](https://github.com/FlutterGen/flutter_gen) - The Flutter code generator for your assets, fonts, colors, … — Get rid of all String-based APIs.
1. [flutter_launcher_icons](https://github.com/fluttercommunity/flutter_launcher_icons) - A package which simplifies the task of updating your Flutter app's launcher icon.
1. [flutter_lints](https://pub.dev/packages/flutter_lints) - Recommended lints for Flutter apps, packages, and plugins to encourage good coding practices.
1. [hive_generator](https://github.com/hivedb/hive/tree/master/hive_generator) - Extension for Hive. Automatically generates TypeAdapters to store any class.
1. [json_serializable](https://pub.dev/packages/json_serializable) - Automatically generate code for converting to and from JSON by annotating Dart classes.
-1. [pub_api_client](https://github.com/leoafarias/pub_api_client) - An API Client for Pub to interact with public package information.
-1. [pubspec_parse](https://pub.dev/packages/pubspec_parse) - Simple package for parsing pubspec.yaml files with a type-safe API and rich error reporting.
1. [freezed](https://pub.dev/packages/freezed) - Code generation for immutable classes that has a simple syntax/API without compromising on the features.
+1. [custom_lint](https://pub.dev/packages/custom_lint) - Lint rules are a powerful way to improve the maintainability of a project. Custom Lint allows package authors and developers to easily write custom lint rules.
+1. [riverpod_lint](https://riverpod.dev) - Riverpod_lint is a developer tool for users of Riverpod, designed to help stop common issues and simplify repetitive tasks.
1. [flutter_desktop_tools](https://github.com/KRTirtho/flutter_desktop_tools) - Essential collection of tools for flutter desktop app development
1. [piped_client](https://github.com/KRTirtho/piped_client) - API Client for piped.video
1. [scrobblenaut](https://github.com/Nebulino/Scrobblenaut) - A deadly simple LastFM API Wrapper for Dart. So deadly simple that it's gonna hit the mark.
diff --git a/lib/collections/env.dart b/lib/collections/env.dart
index 50fe1e6a..14f33b80 100644
--- a/lib/collections/env.dart
+++ b/lib/collections/env.dart
@@ -1,5 +1,5 @@
import 'package:envied/envied.dart';
-import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
+import 'package:spotube/utils/platform.dart';
part 'env.g.dart';
@@ -26,7 +26,7 @@ abstract class Env {
static final String _enableUpdateChecker = _Env._enableUpdateChecker;
static bool get enableUpdateChecker =>
- DesktopTools.platform.isFlatpak || _enableUpdateChecker == "1";
+ kIsFlatpak || _enableUpdateChecker == "1";
static String discordAppId = "1176718791388975124";
}
diff --git a/lib/collections/initializers.dart b/lib/collections/initializers.dart
index 9627de1c..976661fc 100644
--- a/lib/collections/initializers.dart
+++ b/lib/collections/initializers.dart
@@ -1,9 +1,10 @@
import 'dart:io';
-import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
+
+import 'package:spotube/utils/platform.dart';
import 'package:win32_registry/win32_registry.dart';
Future registerWindowsScheme(String scheme) async {
- if (!DesktopTools.platform.isWindows) return;
+ if (!kIsWindows) return;
String appPath = Platform.resolvedExecutable;
String protocolRegKey = 'Software\\Classes\\$scheme';
diff --git a/lib/collections/language_codes.dart b/lib/collections/language_codes.dart
index bd3f8740..45456d69 100644
--- a/lib/collections/language_codes.dart
+++ b/lib/collections/language_codes.dart
@@ -157,10 +157,10 @@ abstract class LanguageLocals {
// name: "Croatian",
// nativeName: "hrvatski",
// ),
- // "cs": const ISOLanguageName(
- // name: "Czech",
- // nativeName: "česky, čeština",
- // ),
+ "cs": const ISOLanguageName(
+ name: "Czech",
+ nativeName: "česky, čeština",
+ ),
// "da": const ISOLanguageName(
// name: "Danish",
// nativeName: "dansk",
diff --git a/lib/components/connect/connect_device.dart b/lib/components/connect/connect_device.dart
index 14243fa8..3ac585df 100644
--- a/lib/components/connect/connect_device.dart
+++ b/lib/components/connect/connect_device.dart
@@ -52,52 +52,58 @@ class ConnectDeviceButton extends HookConsumerWidget {
alignment: Alignment.centerRight,
fit: StackFit.loose,
children: [
- Center(
- child: InkWell(
- onTap: () {
- ServiceUtils.push(context, "/connect");
- },
- borderRadius: BorderRadius.circular(50),
- child: Ink(
- decoration: BoxDecoration(
+ Material(
+ type: MaterialType.transparency,
+ child: Center(
+ child: ClipRect(
+ clipBehavior: Clip.hardEdge,
+ child: InkWell(
+ onTap: () {
+ ServiceUtils.push(context, "/connect");
+ },
borderRadius: BorderRadius.circular(50),
- color: colorScheme.primaryContainer,
- ),
- padding:
- const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
- child: Row(
- mainAxisSize: MainAxisSize.min,
- children: [
- if (connectClients.asData?.value.resolvedService !=
- null) ...[
- Container(
- width: 7,
- height: 7,
- decoration: BoxDecoration(
- color: Colors.greenAccent,
- borderRadius: BorderRadius.circular(50),
- ),
- ),
- const Gap(5),
- ],
- Text(context.l10n.devices),
- if (connectClients.asData?.value.services.isNotEmpty ==
- true)
- Text(
- " (${connectClients.asData?.value.services.length})",
- style: TextStyle(
- color:
- colorScheme.onPrimaryContainer.withOpacity(0.5),
- ),
- ),
- const Gap(35),
- ],
+ child: Ink(
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.circular(50),
+ color: colorScheme.primaryContainer,
+ ),
+ padding:
+ const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
+ child: Row(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ if (connectClients.asData?.value.resolvedService !=
+ null) ...[
+ Container(
+ width: 7,
+ height: 7,
+ decoration: BoxDecoration(
+ color: Colors.greenAccent,
+ borderRadius: BorderRadius.circular(50),
+ ),
+ ),
+ const Gap(5),
+ ],
+ Text(context.l10n.devices),
+ if (connectClients.asData?.value.services.isNotEmpty ==
+ true)
+ Text(
+ " (${connectClients.asData?.value.services.length})",
+ style: TextStyle(
+ color: colorScheme.onPrimaryContainer
+ .withOpacity(0.5),
+ ),
+ ),
+ const Gap(35),
+ ],
+ ),
+ ),
),
),
),
),
Positioned(
- right: 0,
+ right: -3,
child: IconButton.filled(
icon: const Icon(SpotubeIcons.speaker),
style: IconButton.styleFrom(
diff --git a/lib/components/desktop_login/login_form.dart b/lib/components/desktop_login/login_form.dart
index 2949fbae..6091829c 100644
--- a/lib/components/desktop_login/login_form.dart
+++ b/lib/components/desktop_login/login_form.dart
@@ -16,7 +16,6 @@ class TokenLoginForm extends HookConsumerWidget {
Widget build(BuildContext context, ref) {
final authenticationNotifier = ref.watch(authenticationProvider.notifier);
final directCodeController = useTextEditingController();
- final mounted = useIsMounted();
final isLoading = useState(false);
@@ -57,7 +56,7 @@ class TokenLoginForm extends HookConsumerWidget {
await AuthenticationCredentials.fromCookie(
cookieHeader),
);
- if (mounted()) {
+ if (context.mounted) {
onDone?.call();
}
} finally {
diff --git a/lib/components/home/sections/friends.dart b/lib/components/home/sections/friends.dart
index 35ec09b0..4ae802e6 100644
--- a/lib/components/home/sections/friends.dart
+++ b/lib/components/home/sections/friends.dart
@@ -1,12 +1,14 @@
import 'dart:ui';
import 'package:flutter/material.dart';
+import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:skeletonizer/skeletonizer.dart';
import 'package:spotube/collections/fake.dart';
import 'package:spotube/components/home/sections/friends/friend_item.dart';
import 'package:spotube/hooks/utils/use_breakpoint_value.dart';
import 'package:spotube/models/spotify_friends.dart';
+import 'package:spotube/provider/authentication_provider.dart';
import 'package:spotube/provider/spotify/spotify.dart';
class HomePageFriendsSection extends HookConsumerWidget {
@@ -14,6 +16,7 @@ class HomePageFriendsSection extends HookConsumerWidget {
@override
Widget build(BuildContext context, ref) {
+ final auth = ref.watch(authenticationProvider);
final friendsQuery = ref.watch(friendsProvider);
final friends =
friendsQuery.asData?.value.friends ?? FakeData.friends.friends;
@@ -27,32 +30,36 @@ class HomePageFriendsSection extends HookConsumerWidget {
xxl: 7,
);
- final friendGroup = friends.fold>>(
- [],
- (previousValue, element) {
- if (previousValue.isEmpty) {
+ final friendGroup = useMemoized(
+ () => friends.fold>>(
+ [],
+ (previousValue, element) {
+ if (previousValue.isEmpty) {
+ return [
+ [element]
+ ];
+ }
+
+ final lastGroup = previousValue.last;
+ if (lastGroup.length < groupCount) {
+ return [
+ ...previousValue.sublist(0, previousValue.length - 1),
+ [...lastGroup, element]
+ ];
+ }
+
return [
+ ...previousValue,
[element]
];
- }
-
- final lastGroup = previousValue.last;
- if (lastGroup.length < groupCount) {
- return [
- ...previousValue.sublist(0, previousValue.length - 1),
- [...lastGroup, element]
- ];
- }
-
- return [
- ...previousValue,
- [element]
- ];
- },
+ },
+ ),
+ [friends, groupCount],
);
if (friendsQuery.isLoading ||
- friendsQuery.asData?.value.friends.isEmpty == true) {
+ friendsQuery.asData?.value.friends.isEmpty == true ||
+ auth == null) {
return const SliverToBoxAdapter(
child: SizedBox.shrink(),
);
diff --git a/lib/components/library/user_albums.dart b/lib/components/library/user_albums.dart
index 43fa0165..e1b82113 100644
--- a/lib/components/library/user_albums.dart
+++ b/lib/components/library/user_albums.dart
@@ -2,17 +2,17 @@ import 'package:flutter/material.dart' hide Image;
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:collection/collection.dart';
import 'package:fuzzywuzzy/fuzzywuzzy.dart';
+import 'package:gap/gap.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:skeletonizer/skeletonizer.dart';
import 'package:spotube/collections/fake.dart';
import 'package:spotube/collections/spotube_icons.dart';
import 'package:spotube/components/album/album_card.dart';
-import 'package:spotube/components/shared/fallbacks/not_found.dart';
import 'package:spotube/components/shared/inter_scrollbar/inter_scrollbar.dart';
import 'package:spotube/components/shared/fallbacks/anonymous_fallback.dart';
import 'package:spotube/components/shared/waypoint.dart';
-import 'package:spotube/extensions/album_simple.dart';
+import 'package:spotube/extensions/constrains.dart';
import 'package:spotube/extensions/context.dart';
import 'package:spotube/provider/authentication_provider.dart';
import 'package:spotube/provider/spotify/spotify.dart';
@@ -50,71 +50,65 @@ class UserAlbums extends HookConsumerWidget {
return const AnonymousFallback();
}
- final theme = Theme.of(context);
-
- return RefreshIndicator(
- onRefresh: () async {
- ref.invalidate(favoriteAlbumsProvider);
- },
- child: SafeArea(
- child: Scaffold(
- appBar: PreferredSize(
- preferredSize: const Size.fromHeight(50),
- child: Padding(
- padding: const EdgeInsets.symmetric(horizontal: 8.0),
- child: ColoredBox(
- color: theme.scaffoldBackgroundColor,
- child: SearchBar(
- onChanged: (value) => searchText.value = value,
- leading: const Icon(SpotubeIcons.filter),
- hintText: context.l10n.filter_albums,
- ),
- ),
- ),
- ),
- body: SizedBox.expand(
- child: InterScrollbar(
+ return SafeArea(
+ child: Scaffold(
+ body: RefreshIndicator(
+ onRefresh: () async {
+ ref.invalidate(favoriteAlbumsProvider);
+ },
+ child: InterScrollbar(
+ controller: controller,
+ child: CustomScrollView(
controller: controller,
- child: SingleChildScrollView(
- padding: const EdgeInsets.all(8.0),
- controller: controller,
- child: Skeletonizer(
- enabled: albumsQuery.isLoading,
- child: Center(
- child: Wrap(
- runSpacing: 20,
- alignment: WrapAlignment.center,
- runAlignment: WrapAlignment.center,
- crossAxisAlignment: WrapCrossAlignment.center,
- children: [
- if (albumsQuery.asData?.value == null ||
- albumsQuery.asData!.value.items.isEmpty)
- ...List.generate(
- 10,
- (index) => AlbumCard(FakeData.album),
- )
- else if (albums.isEmpty)
- const Row(
- mainAxisAlignment: MainAxisAlignment.center,
- children: [NotFound()],
- ),
- for (final album in albums) AlbumCard(album.toAlbum()),
- if (albums.isNotEmpty &&
- albumsQuery.asData?.value.hasMore == true)
- Skeletonizer(
- enabled: true,
- child: Waypoint(
- controller: controller,
- isGrid: true,
- onTouchEdge: albumsQueryNotifier.fetchMore,
- child: AlbumCard(FakeData.album),
- ),
- )
- ],
+ slivers: [
+ SliverAppBar(
+ floating: true,
+ flexibleSpace: Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 8.0),
+ child: SearchBar(
+ onChanged: (value) => searchText.value = value,
+ leading: const Icon(SpotubeIcons.filter),
+ hintText: context.l10n.filter_albums,
),
),
),
- ),
+ const SliverGap(10),
+ Skeletonizer.sliver(
+ enabled: albumsQuery.isLoading,
+ child: SliverLayoutBuilder(builder: (context, constrains) {
+ return SliverGrid.builder(
+ itemCount: albums.isEmpty ? 6 : albums.length + 1,
+ gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
+ maxCrossAxisExtent: 200,
+ mainAxisExtent: constrains.smAndDown ? 225 : 250,
+ crossAxisSpacing: 8,
+ mainAxisSpacing: 8,
+ ),
+ itemBuilder: (context, index) {
+ if (albums.isNotEmpty && index == albums.length) {
+ if (albumsQuery.asData?.value.hasMore != true) {
+ return const SizedBox.shrink();
+ }
+
+ return Waypoint(
+ controller: controller,
+ isGrid: true,
+ onTouchEdge: albumsQueryNotifier.fetchMore,
+ child: Skeletonizer(
+ enabled: true,
+ child: AlbumCard(FakeData.albumSimple),
+ ),
+ );
+ }
+
+ return AlbumCard(
+ albums.elementAtOrNull(index) ?? FakeData.albumSimple,
+ );
+ },
+ );
+ }),
+ ),
+ ],
),
),
),
diff --git a/lib/components/library/user_artists.dart b/lib/components/library/user_artists.dart
index 83db35c6..0ef0ff39 100644
--- a/lib/components/library/user_artists.dart
+++ b/lib/components/library/user_artists.dart
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:collection/collection.dart';
import 'package:fuzzywuzzy/fuzzywuzzy.dart';
+import 'package:gap/gap.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:skeletonizer/skeletonizer.dart';
import 'package:spotube/collections/fake.dart';
@@ -9,8 +10,9 @@ import 'package:spotube/collections/fake.dart';
import 'package:spotube/collections/spotube_icons.dart';
import 'package:spotube/components/shared/fallbacks/anonymous_fallback.dart';
import 'package:spotube/components/artist/artist_card.dart';
-import 'package:spotube/components/shared/fallbacks/not_found.dart';
import 'package:spotube/components/shared/inter_scrollbar/inter_scrollbar.dart';
+import 'package:spotube/components/shared/waypoint.dart';
+import 'package:spotube/extensions/constrains.dart';
import 'package:spotube/extensions/context.dart';
import 'package:spotube/provider/authentication_provider.dart';
import 'package:spotube/provider/spotify/spotify.dart';
@@ -20,10 +22,10 @@ class UserArtists extends HookConsumerWidget {
@override
Widget build(BuildContext context, ref) {
- final theme = Theme.of(context);
final auth = ref.watch(authenticationProvider);
final artistQuery = ref.watch(followedArtistsProvider);
+ final artistQueryNotifier = ref.watch(followedArtistsProvider.notifier);
final searchText = useState('');
@@ -50,77 +52,73 @@ class UserArtists extends HookConsumerWidget {
return const AnonymousFallback();
}
- return Scaffold(
- appBar: PreferredSize(
- preferredSize: const Size.fromHeight(50),
- child: Padding(
- padding: const EdgeInsets.symmetric(horizontal: 8.0),
- child: ColoredBox(
- color: theme.scaffoldBackgroundColor,
- child: SearchBar(
- onChanged: (value) => searchText.value = value,
- leading: const Icon(SpotubeIcons.filter),
- hintText: context.l10n.filter_artist,
+ return SafeArea(
+ child: Scaffold(
+ body: RefreshIndicator(
+ onRefresh: () async {
+ ref.invalidate(followedArtistsProvider);
+ },
+ child: InterScrollbar(
+ controller: controller,
+ child: Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 8.0),
+ child: CustomScrollView(
+ controller: controller,
+ slivers: [
+ SliverAppBar(
+ floating: true,
+ flexibleSpace: SearchBar(
+ onChanged: (value) => searchText.value = value,
+ leading: const Icon(SpotubeIcons.filter),
+ hintText: context.l10n.filter_artist,
+ ),
+ ),
+ const SliverGap(10),
+ Skeletonizer.sliver(
+ enabled: artistQuery.isLoading,
+ child: SliverLayoutBuilder(builder: (context, constrains) {
+ return SliverGrid.builder(
+ itemCount: filteredArtists.isEmpty
+ ? 6
+ : filteredArtists.length + 1,
+ gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
+ maxCrossAxisExtent: 200,
+ mainAxisExtent: constrains.smAndDown ? 225 : 250,
+ crossAxisSpacing: 8,
+ mainAxisSpacing: 8,
+ ),
+ itemBuilder: (context, index) {
+ if (filteredArtists.isNotEmpty &&
+ index == filteredArtists.length) {
+ if (artistQuery.asData?.value.hasMore != true) {
+ return const SizedBox.shrink();
+ }
+
+ return Waypoint(
+ controller: controller,
+ isGrid: true,
+ onTouchEdge: artistQueryNotifier.fetchMore,
+ child: Skeletonizer(
+ enabled: true,
+ child: ArtistCard(FakeData.artist),
+ ),
+ );
+ }
+
+ return ArtistCard(
+ filteredArtists.elementAtOrNull(index) ??
+ FakeData.artist,
+ );
+ },
+ );
+ }),
+ ),
+ ],
+ ),
),
),
),
),
- backgroundColor: theme.scaffoldBackgroundColor,
- body: artistQuery.asData?.value.items.isEmpty == true
- ? Padding(
- padding: const EdgeInsets.all(20),
- child: Row(
- mainAxisAlignment: MainAxisAlignment.center,
- children: [
- const CircularProgressIndicator(),
- const SizedBox(width: 10),
- Text(context.l10n.loading),
- ],
- ),
- )
- : RefreshIndicator(
- onRefresh: () async {
- ref.invalidate(followedArtistsProvider);
- },
- child: InterScrollbar(
- controller: controller,
- child: SingleChildScrollView(
- controller: controller,
- child: SizedBox(
- width: double.infinity,
- child: SafeArea(
- child: Center(
- child: Skeletonizer(
- enabled: artistQuery.isLoading,
- child: Wrap(
- spacing: 15,
- runSpacing: 5,
- children: artistQuery.isLoading
- ? List.generate(
- 10, (index) => ArtistCard(FakeData.artist))
- : filteredArtists.isEmpty
- ? [
- const Row(
- mainAxisAlignment:
- MainAxisAlignment.center,
- children: [
- NotFound(),
- ],
- )
- ]
- : filteredArtists
- .mapIndexed(
- (index, artist) => ArtistCard(artist),
- )
- .toList(),
- ),
- ),
- ),
- ),
- ),
- ),
- ),
- ),
);
}
}
diff --git a/lib/components/library/user_local_tracks.dart b/lib/components/library/user_local_tracks.dart
index f8bd1326..a7b2102b 100644
--- a/lib/components/library/user_local_tracks.dart
+++ b/lib/components/library/user_local_tracks.dart
@@ -176,7 +176,7 @@ class UserLocalTracks extends HookConsumerWidget {
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
- const SizedBox(width: 10),
+ const SizedBox(width: 5),
FilledButton(
onPressed: trackSnapshot.asData?.value != null
? () async {
@@ -212,7 +212,7 @@ class UserLocalTracks extends HookConsumerWidget {
sortBy.value = value;
},
),
- const SizedBox(width: 10),
+ const SizedBox(width: 5),
FilledButton(
child: const Icon(SpotubeIcons.refresh),
onPressed: () {
diff --git a/lib/components/library/user_playlists.dart b/lib/components/library/user_playlists.dart
index 563541de..069dfad9 100644
--- a/lib/components/library/user_playlists.dart
+++ b/lib/components/library/user_playlists.dart
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart' hide Image;
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:fuzzywuzzy/fuzzywuzzy.dart';
import 'package:collection/collection.dart';
+import 'package:gap/gap.dart';
import 'package:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:skeletonizer/skeletonizer.dart';
@@ -18,6 +19,7 @@ import 'package:spotube/extensions/constrains.dart';
import 'package:spotube/extensions/context.dart';
import 'package:spotube/provider/authentication_provider.dart';
import 'package:spotube/provider/spotify/spotify.dart';
+import 'package:spotube/utils/platform.dart';
class UserPlaylists extends HookConsumerWidget {
const UserPlaylists({super.key});
@@ -86,39 +88,37 @@ class UserPlaylists extends HookConsumerWidget {
child: CustomScrollView(
controller: controller,
slivers: [
- SliverToBoxAdapter(
- child: Column(
- mainAxisSize: MainAxisSize.min,
- children: [
- Padding(
- padding: const EdgeInsets.all(10),
- child: SearchBar(
- onChanged: (value) => searchText.value = value,
- hintText: context.l10n.filter_playlists,
- leading: const Icon(SpotubeIcons.filter),
+ SliverAppBar(
+ floating: true,
+ flexibleSpace: Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 8),
+ child: SearchBar(
+ onChanged: (value) => searchText.value = value,
+ hintText: context.l10n.filter_playlists,
+ leading: const Icon(SpotubeIcons.filter),
+ ),
+ ),
+ bottom: PreferredSize(
+ preferredSize:
+ Size.fromHeight(kIsDesktop ? 35 : kToolbarHeight),
+ child: Row(
+ children: [
+ const Gap(10),
+ const PlaylistCreateDialogButton(),
+ const Gap(10),
+ ElevatedButton.icon(
+ icon: const Icon(SpotubeIcons.magic),
+ label: Text(context.l10n.generate_playlist),
+ onPressed: () {
+ GoRouter.of(context).push("/library/generate");
+ },
),
- ),
- Row(
- children: [
- const SizedBox(width: 10),
- const PlaylistCreateDialogButton(),
- const SizedBox(width: 10),
- ElevatedButton.icon(
- icon: const Icon(SpotubeIcons.magic),
- label: Text(context.l10n.generate_playlist),
- onPressed: () {
- GoRouter.of(context).push("/library/generate");
- },
- ),
- const SizedBox(width: 10),
- ],
- ),
- ],
+ const Gap(10),
+ ],
+ ),
),
),
- const SliverToBoxAdapter(
- child: SizedBox(height: 10),
- ),
+ const SliverGap(10),
SliverLayoutBuilder(builder: (context, constrains) {
return SliverGrid.builder(
itemCount: playlists.isEmpty ? 6 : playlists.length + 1,
diff --git a/lib/components/root/bottom_player.dart b/lib/components/root/bottom_player.dart
index 06250131..5429e172 100644
--- a/lib/components/root/bottom_player.dart
+++ b/lib/components/root/bottom_player.dart
@@ -1,6 +1,5 @@
import 'dart:ui';
-import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
@@ -24,6 +23,7 @@ import 'package:spotube/provider/user_preferences/user_preferences_provider.dart
import 'package:spotube/provider/user_preferences/user_preferences_state.dart';
import 'package:spotube/provider/volume_provider.dart';
import 'package:spotube/utils/platform.dart';
+import 'package:window_manager/window_manager.dart';
class BottomPlayer extends HookConsumerWidget {
BottomPlayer({super.key});
@@ -95,19 +95,19 @@ class BottomPlayer extends HookConsumerWidget {
tooltip: context.l10n.mini_player,
icon: const Icon(SpotubeIcons.miniPlayer),
onPressed: () async {
- final prevSize =
- await DesktopTools.window.getSize();
- await DesktopTools.window.setMinimumSize(
+ if (!kIsDesktop) return;
+
+ final prevSize = await windowManager.getSize();
+ await windowManager.setMinimumSize(
const Size(300, 300),
);
- await DesktopTools.window.setAlwaysOnTop(true);
+ await windowManager.setAlwaysOnTop(true);
if (!kIsLinux) {
- await DesktopTools.window.setHasShadow(false);
+ await windowManager.setHasShadow(false);
}
- await DesktopTools.window
+ await windowManager
.setAlignment(Alignment.topRight);
- await DesktopTools.window
- .setSize(const Size(400, 500));
+ await windowManager.setSize(const Size(400, 500));
await Future.delayed(
const Duration(milliseconds: 100),
() async {
diff --git a/lib/components/shared/inter_scrollbar/inter_scrollbar.dart b/lib/components/shared/inter_scrollbar/inter_scrollbar.dart
index 2b3ce319..8a86b643 100644
--- a/lib/components/shared/inter_scrollbar/inter_scrollbar.dart
+++ b/lib/components/shared/inter_scrollbar/inter_scrollbar.dart
@@ -1,7 +1,7 @@
import 'package:draggable_scrollbar/draggable_scrollbar.dart';
import 'package:flutter/material.dart';
-import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
+import 'package:spotube/utils/platform.dart';
class InterScrollbar extends HookWidget {
final Widget child;
@@ -15,7 +15,7 @@ class InterScrollbar extends HookWidget {
@override
Widget build(BuildContext context) {
- if (DesktopTools.platform.isDesktop) return child;
+ if (kIsDesktop) return child;
return DraggableScrollbar.semicircle(
controller: controller,
diff --git a/lib/components/shared/page_window_title_bar.dart b/lib/components/shared/page_window_title_bar.dart
index 37daefa9..f19757f3 100644
--- a/lib/components/shared/page_window_title_bar.dart
+++ b/lib/components/shared/page_window_title_bar.dart
@@ -7,7 +7,8 @@ import 'package:titlebar_buttons/titlebar_buttons.dart';
import 'dart:math';
import 'package:flutter/foundation.dart' show kIsWeb;
import 'dart:io' show Platform;
-import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
+
+import 'package:window_manager/window_manager.dart';
class PageWindowTitleBar extends StatefulHookConsumerWidget
implements PreferredSizeWidget {
@@ -89,7 +90,7 @@ class _PageWindowTitleBarState extends ConsumerState {
final systemTitleBar =
ref.read(userPreferencesProvider.select((s) => s.systemTitleBar));
if (kIsDesktop && !systemTitleBar) {
- DesktopTools.window.startDragging();
+ windowManager.startDragging();
}
}
@@ -107,11 +108,7 @@ class _PageWindowTitleBarState extends ConsumerState {
return SliverPadding(
padding: EdgeInsets.only(
- left: DesktopTools.platform.isMacOS &&
- hasFullscreen &&
- hasLeadingOrCanPop
- ? 65
- : 0,
+ left: kIsMacOS && hasFullscreen && hasLeadingOrCanPop ? 65 : 0,
),
sliver: SliverAppBar(
leading: widget.leading,
@@ -149,11 +146,7 @@ class _PageWindowTitleBarState extends ConsumerState {
onVerticalDragStart: onDrag,
child: Padding(
padding: EdgeInsets.only(
- left: DesktopTools.platform.isMacOS &&
- hasFullscreen &&
- hasLeadingOrCanPop
- ? 65
- : 0,
+ left: kIsMacOS && hasFullscreen && hasLeadingOrCanPop ? 65 : 0,
),
child: AppBar(
leading: widget.leading,
@@ -193,12 +186,12 @@ class WindowTitleBarButtons extends HookConsumerWidget {
const type = ThemeType.auto;
Future onClose() async {
- await DesktopTools.window.close();
+ await windowManager.close();
}
useEffect(() {
if (kIsDesktop) {
- DesktopTools.window.isMaximized().then((value) {
+ windowManager.isMaximized().then((value) {
isMaximized.value = value;
});
}
@@ -235,14 +228,14 @@ class WindowTitleBarButtons extends HookConsumerWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
MinimizeWindowButton(
- onPressed: DesktopTools.window.minimize,
+ onPressed: windowManager.minimize,
colors: colors,
),
if (isMaximized.value != true)
MaximizeWindowButton(
colors: colors,
onPressed: () {
- DesktopTools.window.maximize();
+ windowManager.maximize();
isMaximized.value = true;
},
)
@@ -250,7 +243,7 @@ class WindowTitleBarButtons extends HookConsumerWidget {
RestoreWindowButton(
colors: colors,
onPressed: () {
- DesktopTools.window.unmaximize();
+ windowManager.unmaximize();
isMaximized.value = false;
},
),
@@ -270,16 +263,16 @@ class WindowTitleBarButtons extends HookConsumerWidget {
children: [
DecoratedMinimizeButton(
type: type,
- onPressed: DesktopTools.window.minimize,
+ onPressed: windowManager.minimize,
),
DecoratedMaximizeButton(
type: type,
onPressed: () async {
- if (await DesktopTools.window.isMaximized()) {
- await DesktopTools.window.unmaximize();
+ if (await windowManager.isMaximized()) {
+ await windowManager.unmaximize();
isMaximized.value = false;
} else {
- await DesktopTools.window.maximize();
+ await windowManager.maximize();
isMaximized.value = true;
}
},
diff --git a/lib/components/shared/tracks_view/sections/header/flexible_header.dart b/lib/components/shared/tracks_view/sections/header/flexible_header.dart
index 4a704302..d6e71e8f 100644
--- a/lib/components/shared/tracks_view/sections/header/flexible_header.dart
+++ b/lib/components/shared/tracks_view/sections/header/flexible_header.dart
@@ -1,7 +1,7 @@
import 'dart:ui';
import 'package:flutter/material.dart';
-import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
+
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:spotube/collections/assets.gen.dart';
import 'package:spotube/components/shared/image/universal_image.dart';
@@ -12,6 +12,7 @@ import 'package:spotube/components/shared/tracks_view/track_view_props.dart';
import 'package:gap/gap.dart';
import 'package:spotube/extensions/constrains.dart';
import 'package:spotube/hooks/utils/use_palette_color.dart';
+import 'package:spotube/utils/platform.dart';
class TrackViewFlexHeader extends HookConsumerWidget {
const TrackViewFlexHeader({super.key});
@@ -53,7 +54,7 @@ class TrackViewFlexHeader extends HookConsumerWidget {
floating: false,
pinned: true,
expandedHeight: 450,
- automaticallyImplyLeading: DesktopTools.platform.isMobile,
+ automaticallyImplyLeading: kIsMobile,
backgroundColor: palette.color,
title: isExpanded ? null : Text(props.title, style: headingStyle),
flexibleSpace: FlexibleSpaceBar(
diff --git a/lib/components/shared/tracks_view/track_view.dart b/lib/components/shared/tracks_view/track_view.dart
index eb8f6871..03d628a8 100644
--- a/lib/components/shared/tracks_view/track_view.dart
+++ b/lib/components/shared/tracks_view/track_view.dart
@@ -1,5 +1,5 @@
import 'package:flutter/material.dart';
-import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
+
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:sliver_tools/sliver_tools.dart';
@@ -8,6 +8,7 @@ import 'package:spotube/components/shared/page_window_title_bar.dart';
import 'package:spotube/components/shared/tracks_view/sections/header/flexible_header.dart';
import 'package:spotube/components/shared/tracks_view/sections/body/track_view_body.dart';
import 'package:spotube/components/shared/tracks_view/track_view_props.dart';
+import 'package:spotube/utils/platform.dart';
class TrackView extends HookConsumerWidget {
const TrackView({super.key});
@@ -18,7 +19,7 @@ class TrackView extends HookConsumerWidget {
final controller = useScrollController();
return Scaffold(
- appBar: DesktopTools.platform.isDesktop
+ appBar: kIsDesktop
? const PageWindowTitleBar(
backgroundColor: Colors.transparent,
foregroundColor: Colors.white,
diff --git a/lib/components/shared/waypoint.dart b/lib/components/shared/waypoint.dart
index 08e9088a..cf00e29b 100644
--- a/lib/components/shared/waypoint.dart
+++ b/lib/components/shared/waypoint.dart
@@ -20,8 +20,6 @@ class Waypoint extends HookWidget {
@override
Widget build(BuildContext context) {
- final isMounted = useIsMounted();
-
useEffect(() {
if (isGrid) {
return null;
@@ -32,19 +30,19 @@ class Waypoint extends HookWidget {
// scrollController fetches the next paginated data when the current
// position of the user on the screen has surpassed
- if (controller.position.pixels >= nextPageTrigger && isMounted()) {
+ if (controller.position.pixels >= nextPageTrigger && context.mounted) {
await onTouchEdge?.call();
}
}
WidgetsBinding.instance.addPostFrameCallback((_) {
- if (controller.hasClients && isMounted()) {
+ if (controller.hasClients && context.mounted) {
listener();
controller.addListener(listener);
}
});
return () => controller.removeListener(listener);
- }, [controller, onTouchEdge, isMounted]);
+ }, [controller, onTouchEdge]);
if (isGrid) {
return VisibilityDetector(
diff --git a/lib/hooks/configurators/use_close_behavior.dart b/lib/hooks/configurators/use_close_behavior.dart
index 79b14fa9..3df6a528 100644
--- a/lib/hooks/configurators/use_close_behavior.dart
+++ b/lib/hooks/configurators/use_close_behavior.dart
@@ -1,29 +1,31 @@
import 'dart:io';
-import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:spotube/hooks/configurators/use_window_listener.dart';
import 'package:spotube/provider/user_preferences/user_preferences_provider.dart';
import 'package:spotube/provider/user_preferences/user_preferences_state.dart';
-// ignore: depend_on_referenced_packages
import 'package:local_notifier/local_notifier.dart';
+import 'package:spotube/utils/platform.dart';
+import 'package:window_manager/window_manager.dart';
-final closeNotification = DesktopTools.createNotification(
- title: 'Spotube',
- message: 'Running in background. Minimized to System Tray',
- actions: [
- LocalNotificationAction(text: 'Close The App'),
- ],
-)?..onClickAction = (value) {
- exit(0);
- };
+final closeNotification = !kIsDesktop
+ ? null
+ : (LocalNotification(
+ title: 'Spotube',
+ body: 'Running in background. Minimized to System Tray',
+ actions: [
+ LocalNotificationAction(text: 'Close The App'),
+ ],
+ )..onClickAction = (value) {
+ exit(0);
+ });
void useCloseBehavior(WidgetRef ref) {
useWindowListener(
onWindowClose: () async {
final preferences = ref.read(userPreferencesProvider);
if (preferences.closeBehavior == CloseBehavior.minimizeToTray) {
- await DesktopTools.window.hide();
+ await windowManager.hide();
closeNotification?.show();
} else {
exit(0);
diff --git a/lib/hooks/configurators/use_deep_linking.dart b/lib/hooks/configurators/use_deep_linking.dart
index 2650b05c..90d062dc 100644
--- a/lib/hooks/configurators/use_deep_linking.dart
+++ b/lib/hooks/configurators/use_deep_linking.dart
@@ -7,7 +7,7 @@ import 'package:spotube/collections/routes.dart';
import 'package:spotube/provider/spotify_provider.dart';
import 'package:flutter_sharing_intent/flutter_sharing_intent.dart';
import 'package:flutter_sharing_intent/model/sharing_file.dart';
-import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
+import 'package:spotube/utils/platform.dart';
final appLinks = AppLinks();
final linkStream = appLinks.allStringLinkStream.asBroadcastStream();
@@ -53,7 +53,7 @@ void useDeepLinking(WidgetRef ref) {
StreamSubscription? mediaStream;
- if (DesktopTools.platform.isMobile) {
+ if (kIsMobile) {
FlutterSharingIntent.instance.getInitialSharing().then(uriListener);
mediaStream =
diff --git a/lib/hooks/configurators/use_disable_battery_optimizations.dart b/lib/hooks/configurators/use_disable_battery_optimizations.dart
index a9afef45..4aa51b74 100644
--- a/lib/hooks/configurators/use_disable_battery_optimizations.dart
+++ b/lib/hooks/configurators/use_disable_battery_optimizations.dart
@@ -1,12 +1,12 @@
import 'package:disable_battery_optimization/disable_battery_optimization.dart';
-import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
+
import 'package:spotube/hooks/utils/use_async_effect.dart';
import 'package:spotube/services/kv_store/kv_store.dart';
+import 'package:spotube/utils/platform.dart';
void useDisableBatteryOptimizations() {
useAsyncEffect(() async {
- if (!DesktopTools.platform.isAndroid ||
- KVStoreService.askedForBatteryOptimization) return;
+ if (!kIsAndroid || KVStoreService.askedForBatteryOptimization) return;
await DisableBatteryOptimization.showDisableBatteryOptimizationSettings();
diff --git a/lib/hooks/configurators/use_get_storage_perms.dart b/lib/hooks/configurators/use_get_storage_perms.dart
index 86b495c4..bcc34042 100644
--- a/lib/hooks/configurators/use_get_storage_perms.dart
+++ b/lib/hooks/configurators/use_get_storage_perms.dart
@@ -1,17 +1,18 @@
import 'package:device_info_plus/device_info_plus.dart';
-import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
+
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:spotube/components/library/user_local_tracks.dart';
import 'package:spotube/hooks/utils/use_async_effect.dart';
+import 'package:spotube/utils/platform.dart';
void useGetStoragePermissions(WidgetRef ref) {
- final isMounted = useIsMounted();
+ final context = useContext();
useAsyncEffect(
() async {
- if (!DesktopTools.platform.isMobile) return;
+ if (!kIsMobile) return;
final androidInfo = await DeviceInfoPlugin().androidInfo;
@@ -25,11 +26,11 @@ void useGetStoragePermissions(WidgetRef ref) {
if (hasNoStoragePerm) {
await Permission.storage.request();
- if (isMounted()) ref.invalidate(localTracksProvider);
+ if (context.mounted) ref.invalidate(localTracksProvider);
}
if (hasNoAudioPerm) {
await Permission.audio.request();
- if (isMounted()) ref.invalidate(localTracksProvider);
+ if (context.mounted) ref.invalidate(localTracksProvider);
}
},
null,
diff --git a/lib/hooks/configurators/use_init_sys_tray.dart b/lib/hooks/configurators/use_init_sys_tray.dart
deleted file mode 100644
index 0bce6727..00000000
--- a/lib/hooks/configurators/use_init_sys_tray.dart
+++ /dev/null
@@ -1,128 +0,0 @@
-import 'dart:io';
-
-import 'package:flutter/material.dart';
-import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
-import 'package:flutter_hooks/flutter_hooks.dart';
-import 'package:hooks_riverpod/hooks_riverpod.dart';
-import 'package:spotube/collections/intents.dart';
-import 'package:spotube/provider/proxy_playlist/proxy_playlist.dart';
-import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart';
-import 'package:spotube/provider/user_preferences/user_preferences_provider.dart';
-
-void useInitSysTray(WidgetRef ref) {
- final context = useContext();
- final systemTray = useRef(null);
-
- final initializeMenu = useCallback(() async {
- systemTray.value?.destroy();
- final playlist = ref.read(proxyPlaylistProvider);
- final playlistQueue = ref.read(proxyPlaylistProvider.notifier);
- final preferences = ref.read(userPreferencesProvider);
- if (!preferences.showSystemTrayIcon) {
- await systemTray.value?.destroy();
- systemTray.value = null;
- return;
- }
- final enabled = !playlist.isFetching;
- systemTray.value = await DesktopTools.createSystemTrayMenu(
- title: DesktopTools.platform.isWindows ? "Spotube" : "",
- iconPath: "assets/spotube-logo.png",
- windowsIconPath: "assets/spotube-logo.ico",
- items: [
- MenuItemLabel(
- label: "Show/Hide",
- name: "show-hide",
- onClicked: (item) async {
- if (await DesktopTools.window.isVisible()) {
- await DesktopTools.window.hide();
- } else {
- await DesktopTools.window.show();
- }
- },
- ),
- MenuSeparator(),
- MenuItemLabel(
- label: "Play/Pause",
- name: "play-pause",
- enabled: enabled,
- onClicked: (_) async {
- Actions.maybeInvoke(
- context, PlayPauseIntent(ref)) ??
- PlayPauseAction().invoke(PlayPauseIntent(ref));
- },
- ),
- MenuItemLabel(
- label: "Next",
- name: "next",
- enabled: enabled && (playlist.tracks.length) > 1,
- onClicked: (p0) async {
- await playlistQueue.next();
- },
- ),
- MenuItemLabel(
- label: "Previous",
- name: "previous",
- enabled: enabled && (playlist.tracks.length) > 1,
- onClicked: (p0) async {
- await playlistQueue.previous();
- },
- ),
- MenuSeparator(),
- MenuItemLabel(
- label: "Quit",
- name: "quit",
- onClicked: (item) async {
- exit(0);
- },
- ),
- ],
- onEvent: (event, tray) async {
- if (DesktopTools.platform.isWindows) {
- switch (event) {
- case SystemTrayEvent.click:
- await DesktopTools.window.show();
- break;
- case SystemTrayEvent.rightClick:
- await tray.popUpContextMenu();
- break;
- default:
- }
- } else {
- switch (event) {
- case SystemTrayEvent.rightClick:
- await DesktopTools.window.show();
- break;
- case SystemTrayEvent.click:
- await tray.popUpContextMenu();
- break;
- default:
- }
- }
- },
- );
- }, [ref]);
-
- useReassemble(initializeMenu);
-
- ref.listen(
- proxyPlaylistProvider,
- (previous, next) {
- initializeMenu();
- },
- );
- ref.listen(
- userPreferencesProvider.select((s) => s.showSystemTrayIcon),
- (previous, next) {
- initializeMenu();
- },
- );
-
- useEffect(() {
- WidgetsBinding.instance.addPostFrameCallback((_) {
- initializeMenu();
- });
- return () async {
- await systemTray.value?.destroy();
- };
- }, [initializeMenu]);
-}
diff --git a/lib/hooks/configurators/use_update_checker.dart b/lib/hooks/configurators/use_update_checker.dart
index 1a6a5be5..7b937efb 100644
--- a/lib/hooks/configurators/use_update_checker.dart
+++ b/lib/hooks/configurators/use_update_checker.dart
@@ -62,7 +62,7 @@ void useUpdateChecker(WidgetRef ref) {
barrierColor: Colors.black26,
builder: (context) {
const url =
- "https://spotube.krtirtho.dev/other-downloads/stable-downloads";
+ "https://spotube.krtirtho.dev/downloads";
return AlertDialog(
title: const Text("Spotube has an update"),
actions: [
diff --git a/lib/hooks/configurators/use_window_listener.dart b/lib/hooks/configurators/use_window_listener.dart
index b91ad413..5977ea8e 100644
--- a/lib/hooks/configurators/use_window_listener.dart
+++ b/lib/hooks/configurators/use_window_listener.dart
@@ -1,6 +1,8 @@
import 'package:flutter/widgets.dart';
-import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
+
import 'package:flutter_hooks/flutter_hooks.dart';
+import 'package:spotube/utils/platform.dart';
+import 'package:window_manager/window_manager.dart';
class CallbackWindowListener implements WindowListener {
final VoidCallback? _onWindowClose;
@@ -154,6 +156,8 @@ void useWindowListener({
VoidCallback? onWindowEvent,
}) {
useEffect(() {
+ if (!kIsDesktop) return null;
+
final listener = CallbackWindowListener(
onWindowClose: onWindowClose,
onWindowFocus: onWindowFocus,
@@ -172,9 +176,9 @@ void useWindowListener({
onWindowUndocked: onWindowUndocked,
onWindowEvent: onWindowEvent,
);
- DesktopTools.window.addListener(listener);
+ windowManager.addListener(listener);
return () {
- DesktopTools.window.removeListener(listener);
+ windowManager.removeListener(listener);
};
}, [
onWindowClose,
diff --git a/lib/hooks/utils/use_palette_color.dart b/lib/hooks/utils/use_palette_color.dart
index 9269edd7..e6d8b398 100644
--- a/lib/hooks/utils/use_palette_color.dart
+++ b/lib/hooks/utils/use_palette_color.dart
@@ -14,7 +14,6 @@ PaletteColor usePaletteColor(String imageUrl, WidgetRef ref) {
final context = useContext();
final theme = Theme.of(context);
final paletteColor = ref.watch(_paletteColorState);
- final mounted = useIsMounted();
useEffect(() {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
@@ -25,7 +24,7 @@ PaletteColor usePaletteColor(String imageUrl, WidgetRef ref) {
width: 50,
),
);
- if (!mounted()) return;
+ if (!context.mounted) return;
final color = theme.brightness == Brightness.light
? palette.lightMutedColor ?? palette.lightVibrantColor
: palette.darkMutedColor ?? palette.darkVibrantColor;
@@ -41,7 +40,7 @@ PaletteColor usePaletteColor(String imageUrl, WidgetRef ref) {
PaletteGenerator usePaletteGenerator(String imageUrl) {
final palette = useState(PaletteGenerator.fromColors([]));
- final mounted = useIsMounted();
+ final context = useContext();
useEffect(() {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
@@ -52,7 +51,7 @@ PaletteGenerator usePaletteGenerator(String imageUrl) {
width: 50,
),
);
- if (!mounted()) return;
+ if (!context.mounted) return;
palette.value = newPalette;
});
diff --git a/lib/l10n/app_ar.arb b/lib/l10n/app_ar.arb
index 41fab083..68308ba1 100644
--- a/lib/l10n/app_ar.arb
+++ b/lib/l10n/app_ar.arb
@@ -313,5 +313,12 @@
"help_project_grow_description": "Spotube هو مشروع مفتوح المصدر. يمكنك مساعدة هذا المشروع في النمو عن طريق المساهمة في المشروع، أو الإبلاغ عن الأخطاء، أو اقتراح ميزات جديدة.",
"contribute_on_github": "المساهمة على GitHub",
"donate_on_open_collective": "التبرع على Open Collective",
- "browse_anonymously": "تصفح بشكل مجهول"
+ "browse_anonymously": "تصفح بشكل مجهول",
+ "enable_connect": "تمكين الاتصال",
+ "enable_connect_description": "التحكم في Spotube من الأجهزة الأخرى",
+ "devices": "الأجهزة",
+ "select": "اختر",
+ "connect_client_alert": "أنت تتم التحكم بواسطة {client}",
+ "this_device": "هذا الجهاز",
+ "remote": "بعيد"
}
\ No newline at end of file
diff --git a/lib/l10n/app_bn.arb b/lib/l10n/app_bn.arb
index 353ca617..506e78bc 100644
--- a/lib/l10n/app_bn.arb
+++ b/lib/l10n/app_bn.arb
@@ -313,5 +313,12 @@
"help_project_grow_description": "স্পটুব একটি ওপেন সোর্স প্রকল্প। আপনি প্রকল্পে অবদান রাখেন, বাগ রিপোর্ট করেন, বা নতুন বৈশিষ্ট্যগুলি সুপারিশ করেন।",
"contribute_on_github": "গিটহাবে অবদান রাখুন",
"donate_on_open_collective": "ওপেন কলেক্টিভে অনুদান করুন",
- "browse_anonymously": "অজানে ব্রাউজ করুন"
+ "browse_anonymously": "অজানে ব্রাউজ করুন",
+ "enable_connect": "সংযোগ সক্রিয় করুন",
+ "enable_connect_description": "অন্যান্য ডিভাইস থেকে Spotube নিয়ন্ত্রণ করুন",
+ "devices": "ডিভাইস",
+ "select": "নির্বাচন করুন",
+ "connect_client_alert": "আপনি {client} দ্বারা নিয়ন্ত্রিত হচ্ছেন",
+ "this_device": "এই ডিভাইস",
+ "remote": "রিমোট"
}
\ No newline at end of file
diff --git a/lib/l10n/app_ca.arb b/lib/l10n/app_ca.arb
index 9848954a..8faa0d09 100644
--- a/lib/l10n/app_ca.arb
+++ b/lib/l10n/app_ca.arb
@@ -313,5 +313,12 @@
"help_project_grow_description": "Spotube és un projecte de codi obert. Podeu ajudar a fer créixer aquest projecte contribuint al projecte, informant d'errors o suggerint noves funcionalitats.",
"contribute_on_github": "Contribueix a GitHub",
"donate_on_open_collective": "Fes una donació a Open Collective",
- "browse_anonymously": "Navega de manera anònima"
+ "browse_anonymously": "Navega de manera anònima",
+ "enable_connect": "Habilita la connexió",
+ "enable_connect_description": "Controla Spotube des d'altres dispositius",
+ "devices": "Dispositius",
+ "select": "Selecciona",
+ "connect_client_alert": "Estàs sent controlat per {client}",
+ "this_device": "Aquest dispositiu",
+ "remote": "Remot"
}
\ No newline at end of file
diff --git a/lib/l10n/app_cs.arb b/lib/l10n/app_cs.arb
new file mode 100644
index 00000000..52f5bcf8
--- /dev/null
+++ b/lib/l10n/app_cs.arb
@@ -0,0 +1,324 @@
+{
+ "guest": "Host",
+ "browse": "Procházet",
+ "search": "Hledat",
+ "library": "Knihovna",
+ "lyrics": "Texty",
+ "settings": "Nastavení",
+ "genre_categories_filter": "Filtrovat kategorie nebo žánry...",
+ "genre": "Žánr",
+ "personalized": "Personalizované",
+ "featured": "Doporučené",
+ "new_releases": "Nově vydané",
+ "songs": "Skladby",
+ "playing_track": "Hraje {track}",
+ "queue_clear_alert": "Toto vymaže aktuální frontu. {track_length} skladeb bude odstraněno\nChcete pokračovat?",
+ "load_more": "Načíst více",
+ "playlists": "Playlisty",
+ "artists": "Umělci",
+ "albums": "Alba",
+ "tracks": "Skladby",
+ "downloads": "Stahování",
+ "filter_playlists": "Filtrovat playlisty...",
+ "liked_tracks": "Oblíbené skladby",
+ "liked_tracks_description": "Všechny vaše oblíbené skladby",
+ "create_playlist": "Vytvořit playlist",
+ "create_a_playlist": "Vytvořit playlist",
+ "update_playlist": "Aktualizovat playlist",
+ "create": "Vytvořit",
+ "cancel": "Zrušit",
+ "update": "Aktualizovat",
+ "playlist_name": "Název playlistu",
+ "name_of_playlist": "Název playlistu",
+ "description": "Popis",
+ "public": "Veřejné",
+ "collaborative": "Společný",
+ "search_local_tracks": "Hledat místní skladby...",
+ "play": "Přehrát",
+ "delete": "Smazat",
+ "none": "Žádné",
+ "sort_a_z": "Seřadit od A-Z",
+ "sort_z_a": "Seřadit od Z-A",
+ "sort_artist": "Seřadit podle umělce",
+ "sort_album": "Seřadit podle alba",
+ "sort_duration": "Seřadit podle délky",
+ "sort_tracks": "Seřadit skladby",
+ "currently_downloading": "Právě se stahuje ({tracks_length})",
+ "cancel_all": "Zrušit vše",
+ "filter_artist": "Filtrovat umělce...",
+ "followers": "{followers} Sledující",
+ "add_artist_to_blacklist": "Přidat umělce na černou listinu",
+ "top_tracks": "Top skladby",
+ "fans_also_like": "Fanoušci mají také rádi",
+ "loading": "Načítání...",
+ "artist": "Umělec",
+ "blacklisted": "Na černé listině",
+ "following": "Sleduje",
+ "follow": "Sledovat",
+ "artist_url_copied": "URL umělce zkopírována do schránky",
+ "added_to_queue": "Přidáno {tracks} skladeb do fronty",
+ "filter_albums": "Filtrovat alba...",
+ "synced": "Synchronizováno",
+ "plain": "Jednoduché",
+ "shuffle": "Zamíchat",
+ "search_tracks": "Hledat skladby...",
+ "released": "Vydáno",
+ "error": "Chyba {error}",
+ "title": "Název",
+ "time": "Čas",
+ "more_actions": "Více akcí",
+ "download_count": "Stáhnout ({count})",
+ "add_count_to_playlist": "Přidat ({count}) do playlistu",
+ "add_count_to_queue": "Přidat ({count}) do fronty",
+ "play_count_next": "Přehrát ({count}) dalších",
+ "album": "Album",
+ "copied_to_clipboard": "Zkopírováno {data} do schránky",
+ "add_to_following_playlists": "Přidat {track} do následujících playlistů",
+ "add": "Přidat",
+ "added_track_to_queue": "Přidána skladba {track} do fronty",
+ "add_to_queue": "Přidat do fronty",
+ "track_will_play_next": "{track} se přehraje jako další",
+ "play_next": "Přehrát další",
+ "removed_track_from_queue": "Odstraněna skladba {track} z fronty",
+ "remove_from_queue": "Odstranit z fronty",
+ "remove_from_favorites": "Odstranit z oblíbených",
+ "save_as_favorite": "Uložit jako oblíbené",
+ "add_to_playlist": "Přidat do playlistu",
+ "remove_from_playlist": "Odstranit z playlistu",
+ "add_to_blacklist": "Přidat na černou listinu",
+ "remove_from_blacklist": "Odstranit z černé listiny",
+ "share": "Sdílet",
+ "mini_player": "Mini přehrávač",
+ "slide_to_seek": "Táhněte pro posunutí vpřed nebo vzad",
+ "shuffle_playlist": "Zamíchat playlist",
+ "unshuffle_playlist": "Zrušit zamíchání playlistu",
+ "previous_track": "Předchozí skladba",
+ "next_track": "Další skladba",
+ "pause_playback": "Pozastavit přehrávání",
+ "resume_playback": "Pokračovat v přehrávání",
+ "loop_track": "Opakovat skladbu",
+ "repeat_playlist": "Opakovat playlist",
+ "queue": "Fronta",
+ "alternative_track_sources": "Alternativní zdroje skladeb",
+ "download_track": "Stáhnout skladbu",
+ "tracks_in_queue": "{tracks} skladeb ve frontě",
+ "clear_all": "Vymazat vše",
+ "show_hide_ui_on_hover": "Zobrazit/Skrýt UI při najetí",
+ "always_on_top": "Vždy nahoře",
+ "exit_mini_player": "Zavřít mini přehrávač",
+ "download_location": "Umístění stahování",
+ "account": "Účet",
+ "login_with_spotify": "Přihlásit se pomocí Spotify účtu",
+ "connect_with_spotify": "Připojit k Spotify",
+ "logout": "Odhlásit se",
+ "logout_of_this_account": "Odhlásit se z tohoto účtu",
+ "language_region": "Jazyk a region",
+ "language": "Jazyk",
+ "system_default": "Systém",
+ "market_place_region": "Region",
+ "recommendation_country": "Země pro doporučení",
+ "appearance": "Vzhled",
+ "layout_mode": "Režim rozložení",
+ "override_layout_settings": "Přepsat režim rozložení",
+ "adaptive": "Adaptivní",
+ "compact": "Kompaktní",
+ "extended": "Rozšířený",
+ "theme": "Téma",
+ "dark": "Tmavé",
+ "light": "Světlé",
+ "system": "Systém",
+ "accent_color": "Barva akcentu",
+ "sync_album_color": "Synchronizovat barvu alba",
+ "sync_album_color_description": "Používá dominantní barvu obalu alba jako barvu akcentu",
+ "playback": "Přehrávání",
+ "audio_quality": "Kvalita zvuku",
+ "high": "Vysoká",
+ "low": "Nízká",
+ "pre_download_play": "Předstáhnout a přehrát",
+ "pre_download_play_description": "Místo streamování audia stáhnout skladbu a přehrát (doporučeno pro uživatele s rychlejším internetem)",
+ "skip_non_music": "Přeskočit nehudební segmenty (SponsorBlock)",
+ "blacklist_description": "Zakázané skladby a umělci",
+ "wait_for_download_to_finish": "Počkejte, až se dokončí stahování",
+ "desktop": "Desktop",
+ "close_behavior": "Chování při zavření",
+ "close": "Zavřít",
+ "minimize_to_tray": "Minimalizovat do lišty",
+ "show_tray_icon": "Zobrazit ikonu v systémové liště",
+ "about": "O aplikaci",
+ "u_love_spotube": "Víme, že milujete Spotube",
+ "check_for_updates": "Zkontrolovat aktualizace",
+ "about_spotube": "O Spotube",
+ "blacklist": "Černá listina",
+ "please_sponsor": "Sponzorovat/darovat",
+ "spotube_description": "Spotube, rychlý, multiplatformní, bezplatný Spotify klient",
+ "version": "Verze",
+ "build_number": "Číslo sestavení",
+ "founder": "Zakladatel",
+ "repository": "Repozitář",
+ "bug_issues": "Chyby+Problémy",
+ "made_with": "Vytvořeno s ❤️ v Bangladéši🇧🇩",
+ "kingkor_roy_tirtho": "Kingkor Roy Tirtho",
+ "copyright": "© 2021-{current_year} Kingkor Roy Tirtho",
+ "license": "Licence",
+ "add_spotify_credentials": "Přidejte své přihlašovací údaje Spotify a začněte",
+ "credentials_will_not_be_shared_disclaimer": "Nebojte, žádné z vašich údajů nebudou shromažďovány ani s nikým sdíleny",
+ "know_how_to_login": "Nevíte, jak na to?",
+ "follow_step_by_step_guide": "Postupujte podle návodu",
+ "spotify_cookie": "Cookie Spotify {name}",
+ "cookie_name_cookie": "Cookie {name}",
+ "fill_in_all_fields": "Vyplňte prosím všechna pole",
+ "submit": "Odeslat",
+ "exit": "Ukončit",
+ "previous": "Předchozí",
+ "next": "Další",
+ "done": "Hotovo",
+ "step_1": "Krok 1",
+ "first_go_to": "Nejprve jděte na",
+ "login_if_not_logged_in": "a přihlašte se nebo se zaregistrujte, pokud nejste přihlášeni",
+ "step_2": "Krok 2",
+ "step_2_steps": "1. Jakmile jste přihlášeni, stiskněte F12 nebo pravé tlačítko myši > Prozkoumat, abyste otevřeli nástroje pro vývojáře prohlížeče.\n2. Poté přejděte na kartu \"Aplikace\" (Chrome, Edge, Brave atd.) nebo kartu \"Úložiště\" (Firefox, Palemoon atd.)\n3. Přejděte do sekce \"Cookies\" a pak do podsekce \"https://accounts.spotify.com\"",
+ "step_3": "Krok 3",
+ "step_3_steps": "Zkopírujte hodnotu cookie \"sp_dc\"",
+ "success_emoji": "Úspěch🥳",
+ "success_message": "Nyní jste úspěšně přihlášeni pomocí svého Spotify účtu. Dobrá práce, kamaráde!",
+ "step_4": "Krok 4",
+ "step_4_steps": "Vložte zkopírovanou hodnotu \"sp_dc\"",
+ "something_went_wrong": "Něco se pokazilo",
+ "piped_instance": "Instance serveru Piped",
+ "piped_description": "Instance serveru Piped, kterou použít pro hledání skladeb",
+ "piped_warning": "Některé z nich nemusí dobře fungovat. Používejte na vlastní riziko",
+ "generate_playlist": "Vygenerovat playlist",
+ "track_exists": "Skladba {track} již existuje",
+ "replace_downloaded_tracks": "Nahradit všechny stažené skladby",
+ "skip_download_tracks": "Přeskočit stahování všech stažených skladeb",
+ "do_you_want_to_replace": "Chcete nahradit existující skladbu??",
+ "replace": "Nahradit",
+ "skip": "Přeskočit",
+ "select_up_to_count_type": "Vyberte až {count} {type}",
+ "select_genres": "Vyberte žánry",
+ "add_genres": "Přidat žánry",
+ "country": "Země",
+ "number_of_tracks_generate": "Počet skladeb k vygenerování",
+ "acousticness": "Akustičnost",
+ "danceability": "Tanečnost",
+ "energy": "Energie",
+ "instrumentalness": "Instrumentálnost",
+ "liveness": "Živost",
+ "loudness": "Hlasitost",
+ "speechiness": "Mluvnost",
+ "valence": "Valence",
+ "popularity": "Popularita",
+ "key": "Klíč",
+ "duration": "Délka (s)",
+ "tempo": "Tempo (BPM)",
+ "mode": "Režim",
+ "time_signature": "Udání taktu",
+ "short": "Krátký",
+ "medium": "Střední",
+ "long": "Dlouhý",
+ "min": "Min",
+ "max": "Max",
+ "target": "Cíl",
+ "moderate": "Mírný",
+ "deselect_all": "Zrušit výběr",
+ "select_all": "Vybrat vše",
+ "are_you_sure": "Jste si jisti?",
+ "generating_playlist": "Generování vašeho vlastního playlistu...",
+ "selected_count_tracks": "Vybráno {count} skladeb",
+ "download_warning": "Pokud stáhnete všechny skladby najednou, pirátíte tím hudbu a škodíte kreativní společnosti hudby. Doufám, že jste si toho vědomi. Vždy se snažte respektovat a podporovat tvrdou práci umělců",
+ "download_ip_ban_warning": "Mimochodem, vaše IP může být na YouTube zablokována kvůli nadměrným požadavkům na stahování. Blokování IP znamená, že nemůžete používat YouTube (i když jste přihlášeni) alespoň 2-3 měsíce ze zařízení s touto IP. A Spotube nenese žádnou odpovědnost, pokud se to někdy stane",
+ "by_clicking_accept_terms": "Kliknutím na 'přijmout' souhlasíte s následujícími podmínkami:",
+ "download_agreement_1": "Vím, že pirátím hudbu. Jsem špatný",
+ "download_agreement_2": "Budu podporovat umělce, kdekoliv to bude možné, a dělám to jen proto, že nemám peníze na koupi jejich umění",
+ "download_agreement_3": "Jsem si naprosto vědom toho, že moje IP může být na YouTube zablokována a nenesu žádnou odpovědnost za nehody způsobené mým současným jednáním",
+ "decline": "Odmítnout",
+ "accept": "Přijmout",
+ "details": "Podrobnosti",
+ "youtube": "YouTube",
+ "channel": "Kanál",
+ "likes": "Líbí se",
+ "dislikes": "Nelíbí se",
+ "views": "Zobrazení",
+ "streamUrl": "URL streamu",
+ "stop": "Zastavit",
+ "sort_newest": "Seřadit od nejnovějších",
+ "sort_oldest": "Seřadit od nejstarších",
+ "sleep_timer": "Časovač spánku",
+ "mins": "{minutes} Minut",
+ "hours": "{hours} Hodin",
+ "hour": "{hours} Hodina",
+ "custom_hours": "Vlastní hodiny",
+ "logs": "Protokoly",
+ "developers": "Vývojáři",
+ "not_logged_in": "Nejste přihlášeni",
+ "search_mode": "Režim hledání",
+ "audio_source": "Zdroj zvuku",
+ "ok": "Ok",
+ "failed_to_encrypt": "Šifrování selhalo",
+ "encryption_failed_warning": "Spotube používá šifrování k bezpečnému ukládání vašich dat. Ale selhalo. Takže se vrátí k nezabezpečenému úložišti\nPokud používáte linux, ujistěte se, že máte nainstalovanou jakoukoli službu k ukládání bezpečnostních pověření (gnome-keyring, kde-wallet, keepassxc atd.)",
+ "querying_info": "Získávání informací...",
+ "piped_api_down": "Piped API je mimo provoz",
+ "piped_down_error_instructions": "Instance Piped {pipedInstance} je momentálně mimo provoz\n\nBuď změňte instanci nebo změňte 'Typ API' na oficiální YouTube API\n\nPo změně se ujistěte, že aplikaci restartujete",
+ "you_are_offline": "Momentálně jste offline",
+ "connection_restored": "Vaše internetové připojení bylo obnoveno",
+ "use_system_title_bar": "Použít systémové záhlaví okna",
+ "crunching_results": "Zpracovávání výsledků...",
+ "search_to_get_results": "Hledejte pro získání výsledků",
+ "use_amoled_mode": "Úplně černé téma",
+ "pitch_dark_theme": "AMOLED režim",
+ "normalize_audio": "Normalizovat audio",
+ "change_cover": "Změnit obal",
+ "add_cover": "Přidat obal",
+ "restore_defaults": "Obnovit výchozí",
+ "download_music_codec": "Kodek pro stahování",
+ "streaming_music_codec": "Kodek pro streamování",
+ "login_with_lastfm": "Přihlásit se pomocí Last.fm",
+ "connect": "Připojit",
+ "disconnect_lastfm": "Odpojit Last.fm",
+ "disconnect": "Odpojit",
+ "username": "Uživatelské jméno",
+ "password": "Heslo",
+ "login": "Přihlásit se",
+ "login_with_your_lastfm": "Přihlásit se pomocí vašeho Last.fm účtu",
+ "scrobble_to_lastfm": "Scrobble na Last.fm",
+ "go_to_album": "Přejít na album",
+ "discord_rich_presence": "Discord Rich Presence",
+ "browse_all": "Procházet vše",
+ "genres": "Žánry",
+ "explore_genres": "Prozkoumat žánry",
+ "friends": "Přátelé",
+ "no_lyrics_available": "Omlouváme se, není možné najít texty pro tuto skladbu",
+ "start_a_radio": "Vytvořit rádio",
+ "how_to_start_radio": "Jak chcete vytvořit rádio?",
+ "replace_queue_question": "Chcete nahradit aktuální frontu nebo k ní přidat?",
+ "endless_playback": "Nekonečné přehrávání",
+ "delete_playlist": "Smazat playlist",
+ "delete_playlist_confirmation": "Jste si jisti, že chcete smazat tento playlist?",
+ "local_tracks": "Místní skladby",
+ "song_link": "Odkaz na skladbu",
+ "skip_this_nonsense": "Přeskočit tenhle nesmysl",
+ "freedom_of_music": "“Svobodná hudba”",
+ "freedom_of_music_palm": "“Svobodná hudba ve vaší dlani”",
+ "get_started": "Začít",
+ "youtube_source_description": "Doporučeno a funguje nejlépe.",
+ "piped_source_description": "Nechcete být sledováni? Stejné jako YouTube, ale respektuje soukromí.",
+ "jiosaavn_source_description": "Nejlepší pro jihoasijský region.",
+ "highest_quality": "Nejvyšší kvalita: {quality}",
+ "select_audio_source": "Vyberte zdroj zvuku",
+ "endless_playback_description": "Automaticky přidávat nové skladby\nna konec fronty",
+ "choose_your_region": "Vyberte svůj region",
+ "choose_your_region_description": "To pomůže Spotube ukázat vám správný obsah\npro vaši lokalitu.",
+ "choose_your_language": "Vyberte svůj jazyk",
+ "help_project_grow": "Pomozte tomuto projektu růst",
+ "help_project_grow_description": "Spotube je open-source projekt. Můžete pomoci tomuto projektu růst tím, že přispějete do projektu, nahlásíte chyby nebo navrhnete nové funkce.",
+ "contribute_on_github": "Přispějte na GitHub",
+ "donate_on_open_collective": "Darujte na Open Collective",
+ "browse_anonymously": "Procházet anonymně",
+ "enable_connect": "Povolit ovládání",
+ "enable_connect_description": "Ovládejte Spotube z jiného zařízení",
+ "devices": "Zařízení",
+ "select": "Vybrat",
+ "connect_client_alert": "Zařízení je ovládáno z {client}",
+ "this_device": "Toto zařízení",
+ "remote": "Ovladač"
+}
\ No newline at end of file
diff --git a/lib/l10n/app_de.arb b/lib/l10n/app_de.arb
index b058d41a..77435d67 100644
--- a/lib/l10n/app_de.arb
+++ b/lib/l10n/app_de.arb
@@ -313,5 +313,12 @@
"help_project_grow_description": "Spotube ist ein Open-Source-Projekt. Sie können diesem Projekt helfen, indem Sie zum Projekt beitragen, Fehler melden oder neue Funktionen vorschlagen.",
"contribute_on_github": "Auf GitHub beitragen",
"donate_on_open_collective": "Auf Open Collective spenden",
- "browse_anonymously": "Anonym durchsuchen"
+ "browse_anonymously": "Anonym durchsuchen",
+ "enable_connect": "Verbindung aktivieren",
+ "enable_connect_description": "Spotube von anderen Geräten steuern",
+ "devices": "Geräte",
+ "select": "Auswählen",
+ "connect_client_alert": "Du wirst von {client} gesteuert",
+ "this_device": "Dieses Gerät",
+ "remote": "Fernbedienung"
}
\ No newline at end of file
diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb
index 0b4cbb2a..11617b42 100644
--- a/lib/l10n/app_es.arb
+++ b/lib/l10n/app_es.arb
@@ -313,5 +313,12 @@
"help_project_grow_description": "Spotube es un proyecto de código abierto. Puedes ayudar a que este proyecto crezca contribuyendo al proyecto, informando errores o sugiriendo nuevas funciones.",
"contribute_on_github": "Contribuir en GitHub",
"donate_on_open_collective": "Donar en Open Collective",
- "browse_anonymously": "Navegar Anónimamente"
+ "browse_anonymously": "Navegar Anónimamente",
+ "enable_connect": "Habilitar conexión",
+ "enable_connect_description": "Controla Spotube desde otros dispositivos",
+ "devices": "Dispositivos",
+ "select": "Seleccionar",
+ "connect_client_alert": "Estás siendo controlado por {client}",
+ "this_device": "Este dispositivo",
+ "remote": "Remoto"
}
\ No newline at end of file
diff --git a/lib/l10n/app_fa.arb b/lib/l10n/app_fa.arb
index 629238cc..8a0bee3a 100644
--- a/lib/l10n/app_fa.arb
+++ b/lib/l10n/app_fa.arb
@@ -313,5 +313,12 @@
"help_project_grow_description": "Spotube یک پروژه متن باز است. شما میتوانید با به پروژه کمک کردن، گزارش دادن اشکالات یا پیشنهاد ویژگیهای جدید، به این پروژه کمک کنید.",
"contribute_on_github": "مشارکت در GitHub",
"donate_on_open_collective": "کمک مالی در Open Collective",
- "browse_anonymously": "مرور به صورت ناشناس"
+ "browse_anonymously": "مرور به صورت ناشناس",
+ "enable_connect": "فعالسازی اتصال",
+ "enable_connect_description": "کنترل Spotube از دیگر دستگاهها",
+ "devices": "دستگاهها",
+ "select": "انتخاب",
+ "connect_client_alert": "شما توسط {client} کنترل میشوید",
+ "this_device": "این دستگاه",
+ "remote": "راهدور"
}
\ No newline at end of file
diff --git a/lib/l10n/app_fr.arb b/lib/l10n/app_fr.arb
index 69b2bb69..cabcb8e1 100644
--- a/lib/l10n/app_fr.arb
+++ b/lib/l10n/app_fr.arb
@@ -313,5 +313,12 @@
"help_project_grow_description": "Spotube est un projet open-source. Vous pouvez aider ce projet à grandir en contribuant au projet, en signalant des bugs ou en suggérant de nouvelles fonctionnalités.",
"contribute_on_github": "Contribuer sur GitHub",
"donate_on_open_collective": "Faire un don sur Open Collective",
- "browse_anonymously": "Naviguer anonymement"
+ "browse_anonymously": "Naviguer anonymement",
+ "enable_connect": "Activer la connexion",
+ "enable_connect_description": "Contrôlez Spotube depuis d'autres appareils",
+ "devices": "Appareils",
+ "select": "Sélectionner",
+ "connect_client_alert": "Vous êtes contrôlé par {client}",
+ "this_device": "Cet appareil",
+ "remote": "À distance"
}
\ No newline at end of file
diff --git a/lib/l10n/app_hi.arb b/lib/l10n/app_hi.arb
index b442da37..a72e136e 100644
--- a/lib/l10n/app_hi.arb
+++ b/lib/l10n/app_hi.arb
@@ -313,5 +313,12 @@
"help_project_grow_description": "Spotube एक ओपन सोर्स परियोजना है। आप इस परियोजना को योगदान देकर, बग रिपोर्ट करके या नई विशेषताओं का सुझाव देकर इस परियोजना को बढ़ा सकते हैं।",
"contribute_on_github": "GitHub पर योगदान करें",
"donate_on_open_collective": "ओपन कलेक्टिव पर दान करें",
- "browse_anonymously": "बिना नाम के ब्राउज़ करें"
+ "browse_anonymously": "बिना नाम के ब्राउज़ करें",
+ "enable_connect": "कनेक्ट सक्षम करें",
+ "enable_connect_description": "अन्य उपकरणों से Spotube को नियंत्रित करें",
+ "devices": "उपकरण",
+ "select": "चयन करें",
+ "connect_client_alert": "आप {client} द्वारा नियंत्रित हो रहे हैं",
+ "this_device": "यह उपकरण",
+ "remote": "रिमोट"
}
\ No newline at end of file
diff --git a/lib/l10n/app_it.arb b/lib/l10n/app_it.arb
index f8440cd0..bb1881d6 100644
--- a/lib/l10n/app_it.arb
+++ b/lib/l10n/app_it.arb
@@ -314,5 +314,12 @@
"help_project_grow_description": "Spotube è un progetto open-source. Puoi aiutare questo progetto a crescere contribuendo al progetto, segnalando bug o suggerendo nuove funzionalità.",
"contribute_on_github": "Contribuisci su GitHub",
"donate_on_open_collective": "Dona su Open Collective",
- "browse_anonymously": "Naviga in modo anonimo"
+ "browse_anonymously": "Naviga in modo anonimo",
+ "enable_connect": "Abilita connessione",
+ "enable_connect_description": "Controlla Spotube da altri dispositivi",
+ "devices": "Dispositivi",
+ "select": "Seleziona",
+ "connect_client_alert": "Stai venendo controllato da {client}",
+ "this_device": "Questo dispositivo",
+ "remote": "Remoto"
}
\ No newline at end of file
diff --git a/lib/l10n/app_ja.arb b/lib/l10n/app_ja.arb
index ecdc77a2..ab759404 100644
--- a/lib/l10n/app_ja.arb
+++ b/lib/l10n/app_ja.arb
@@ -313,5 +313,12 @@
"help_project_grow_description": "Spotubeはオープンソースプロジェクトです。プロジェクトに貢献したり、バグを報告したり、新しい機能を提案することで、このプロジェクトの成長に貢献できます。",
"contribute_on_github": "GitHubで貢献する",
"donate_on_open_collective": "Open Collectiveで寄付する",
- "browse_anonymously": "匿名で閲覧する"
+ "browse_anonymously": "匿名で閲覧する",
+ "enable_connect": "接続を有効にする",
+ "enable_connect_description": "他のデバイスからSpotubeを制御する",
+ "devices": "デバイス",
+ "select": "選択する",
+ "connect_client_alert": "{client} によって操作されています",
+ "this_device": "このデバイス",
+ "remote": "リモート"
}
\ No newline at end of file
diff --git a/lib/l10n/app_ko.arb b/lib/l10n/app_ko.arb
index 5a3ee8bc..c94f8142 100644
--- a/lib/l10n/app_ko.arb
+++ b/lib/l10n/app_ko.arb
@@ -314,5 +314,12 @@
"help_project_grow_description": "Spotube는 오픈 소스 프로젝트입니다. 프로젝트에 기여하거나 버그를 보고하거나 새로운 기능을 제안하여이 프로젝트의 성장에 도움을 줄 수 있습니다.",
"contribute_on_github": "GitHub에서 기여하기",
"donate_on_open_collective": "Open Collective에 기부하기",
- "browse_anonymously": "익명으로 둘러보기"
+ "browse_anonymously": "익명으로 둘러보기",
+ "enable_connect": "연결 활성화",
+ "enable_connect_description": "다른 장치에서 Spotube 제어",
+ "devices": "장치",
+ "select": "선택",
+ "connect_client_alert": "{client}님에 의해 제어되고 있습니다",
+ "this_device": "이 장치",
+ "remote": "원격"
}
\ No newline at end of file
diff --git a/lib/l10n/app_ne.arb b/lib/l10n/app_ne.arb
index d921f3ba..4085b00e 100644
--- a/lib/l10n/app_ne.arb
+++ b/lib/l10n/app_ne.arb
@@ -313,5 +313,12 @@
"help_project_grow_description": "Spotube एक खुला स्रोतको परियोजना हो। तपाईं परियोजनामा योगदान गरेर, त्रुटिहरू सूचिकै, वा नयाँ सुविधाहरू सुझाव दिएर यस परियोजनामा वृद्धि गर्न सक्नुहुन्छ।",
"contribute_on_github": "GitHubमा योगदान गर्नुहोस्",
"donate_on_open_collective": "खुला संगठनमा दान गर्नुहोस्",
- "browse_anonymously": "अनामित रूपमा ब्राउज़ गर्नुहोस्"
+ "browse_anonymously": "अनामित रूपमा ब्राउज़ गर्नुहोस्",
+ "enable_connect": "कनेक्ट सक्रिय गर्नुहोस्",
+ "enable_connect_description": "अन्य उपकरणहरूबाट Spotube कन्ट्रोल गर्नुहोस्",
+ "devices": "उपकरणहरू",
+ "select": "चयन गर्नुहोस्",
+ "connect_client_alert": "तपाईंलाई {client} द्वारा नियन्त्रित गरिएको छ",
+ "this_device": "यो उपकरण",
+ "remote": "दूरसंचार"
}
\ No newline at end of file
diff --git a/lib/l10n/app_nl.arb b/lib/l10n/app_nl.arb
index 33e94a2e..0a04c40b 100644
--- a/lib/l10n/app_nl.arb
+++ b/lib/l10n/app_nl.arb
@@ -314,5 +314,12 @@
"help_project_grow_description": "Spotube is een open-source project. U kunt dit project helpen groeien door bij te dragen aan het project, bugs te melden of nieuwe functies voor te stellen.",
"contribute_on_github": "Bijdragen op GitHub",
"donate_on_open_collective": "Doneren op Open Collective",
- "browse_anonymously": "Anoniem Bladeren"
+ "browse_anonymously": "Anoniem Bladeren",
+ "enable_connect": "Verbinding inschakelen",
+ "enable_connect_description": "Spotube bedienen vanaf andere apparaten",
+ "devices": "Apparaten",
+ "select": "Selecteren",
+ "connect_client_alert": "Je wordt gecontroleerd door {client}",
+ "this_device": "Dit apparaat",
+ "remote": "Afstandsbediening"
}
\ No newline at end of file
diff --git a/lib/l10n/app_pl.arb b/lib/l10n/app_pl.arb
index a1bc5de6..9ce31187 100644
--- a/lib/l10n/app_pl.arb
+++ b/lib/l10n/app_pl.arb
@@ -313,5 +313,12 @@
"help_project_grow_description": "Spotube to projekt open-source. Możesz pomóc temu projektowi rosnąć, przyczyniając się do projektu, zgłaszając błędy lub sugerując nowe funkcje.",
"contribute_on_github": "Przyczyniaj się na GitHubie",
"donate_on_open_collective": "Dotuj na Open Collective",
- "browse_anonymously": "Przeglądaj Anonimowo"
+ "browse_anonymously": "Przeglądaj Anonimowo",
+ "enable_connect": "Włącz połączenie",
+ "enable_connect_description": "Kontroluj Spotube z innych urządzeń",
+ "devices": "Urządzenia",
+ "select": "Wybierz",
+ "connect_client_alert": "Jesteś sterowany przez {client}",
+ "this_device": "To urządzenie",
+ "remote": "Zdalny"
}
\ No newline at end of file
diff --git a/lib/l10n/app_pt.arb b/lib/l10n/app_pt.arb
index 7f290a1d..53732589 100644
--- a/lib/l10n/app_pt.arb
+++ b/lib/l10n/app_pt.arb
@@ -313,5 +313,12 @@
"help_project_grow_description": "Spotube é um projeto de código aberto. Você pode ajudar este projeto a crescer contribuindo para o projeto, relatando bugs ou sugerindo novos recursos.",
"contribute_on_github": "Contribuir no GitHub",
"donate_on_open_collective": "Doar no Open Collective",
- "browse_anonymously": "Navegar Anonimamente"
+ "browse_anonymously": "Navegar Anonimamente",
+ "enable_connect": "Ativar conexão",
+ "enable_connect_description": "Controle o Spotube a partir de outros dispositivos",
+ "devices": "Dispositivos",
+ "select": "Selecionar",
+ "connect_client_alert": "Você está sendo controlado por {client}",
+ "this_device": "Este dispositivo",
+ "remote": "Remoto"
}
\ No newline at end of file
diff --git a/lib/l10n/app_ru.arb b/lib/l10n/app_ru.arb
index c9139a90..a18e02e7 100644
--- a/lib/l10n/app_ru.arb
+++ b/lib/l10n/app_ru.arb
@@ -313,5 +313,12 @@
"help_project_grow_description": "Spotube - это проект с открытым исходным кодом. Вы можете помочь этому проекту развиваться, внося вклад в проект, сообщая ошибках или предлагая новые функции.",
"contribute_on_github": "Внести вклад на GitHub",
"donate_on_open_collective": "Пожертвовать на Open Collective",
- "browse_anonymously": "Анонимно просматривать"
+ "browse_anonymously": "Анонимно просматривать",
+ "enable_connect": "Включить подключение",
+ "enable_connect_description": "Управление Spotube с других устройств",
+ "devices": "Устройства",
+ "select": "Выбрать",
+ "connect_client_alert": "Вас контролирует {client}",
+ "this_device": "Это устройство",
+ "remote": "Дистанционное управление"
}
\ No newline at end of file
diff --git a/lib/l10n/app_th.arb b/lib/l10n/app_th.arb
index cd58a20d..866929fa 100644
--- a/lib/l10n/app_th.arb
+++ b/lib/l10n/app_th.arb
@@ -313,5 +313,13 @@
"help_project_grow_description": "Spotube เป็นโครงการโอเพนซอร์ส คุณสามารถช่วยให้โครงการนี้เติบโตได้โดยการมีส่วนร่วมในโครงการ รายงานข้อบกพร่อง หรือเสนอคุณสมบัติใหม่",
"contribute_on_github": "มีส่วนร่วมบน GitHub",
"donate_on_open_collective": "บริจาคบน Open Collective",
- "browse_anonymously": "เรียกดูแบบไม่ระบุตัวตน"
+ "browse_anonymously": "เรียกดูแบบไม่ระบุตัวตน",
+ "choose_your_language": "เลือกภาษาของคุณ",
+ "enable_connect": "เปิดใช้งานการเชื่อมต่อ",
+ "enable_connect_description": "ควบคุม Spotube จากอุปกรณ์อื่น",
+ "devices": "อุปกรณ์",
+ "select": "เลือก",
+ "connect_client_alert": "คุณกำลังถูกควบคุมโดย {client}",
+ "this_device": "อุปกรณ์นี้",
+ "remote": "ระยะไกล"
}
\ No newline at end of file
diff --git a/lib/l10n/app_uk.arb b/lib/l10n/app_uk.arb
index fe57e617..4208a3d2 100644
--- a/lib/l10n/app_uk.arb
+++ b/lib/l10n/app_uk.arb
@@ -313,5 +313,12 @@
"help_project_grow_description": "Spotube - це проект з відкритим кодом. Ви можете допомогти цьому проекту зростати, вносячи свій внесок у проект, повідомляючи про помилки або пропонуючи нові функції.",
"contribute_on_github": "Долучайтесь на GitHub",
"donate_on_open_collective": "Пожертвуйте на Open Collective",
- "browse_anonymously": "Анонімно переглядати"
+ "browse_anonymously": "Анонімно переглядати",
+ "enable_connect": "Увімкнути підключення",
+ "enable_connect_description": "Керуйте Spotube з інших пристроїв",
+ "devices": "Пристрої",
+ "select": "Вибрати",
+ "connect_client_alert": "Вас керує {client}",
+ "this_device": "Цей пристрій",
+ "remote": "Віддалений"
}
\ No newline at end of file
diff --git a/lib/l10n/app_vi.arb b/lib/l10n/app_vi.arb
index 0e9b0b7c..6115fc0c 100644
--- a/lib/l10n/app_vi.arb
+++ b/lib/l10n/app_vi.arb
@@ -311,5 +311,14 @@
"help_project_grow_description": "Spotube là một dự án mã nguồn mở. Bạn có thể giúp dự án này phát triển bằng cách đóng góp vào dự án, báo cáo lỗi hoặc đề xuất tính năng mới.",
"contribute_on_github": "Đóng góp trên GitHub",
"donate_on_open_collective": "Quyên góp trên Open Collective",
- "browse_anonymously": "Duyệt Anonymously"
+ "browse_anonymously": "Duyệt Anonymously",
+ "friends": "Bạn bè",
+ "no_lyrics_available": "Xin lỗi, không tìm thấy lời cho bài hát này",
+ "enable_connect": "Kích hoạt kết nối",
+ "enable_connect_description": "Điều khiển Spotube từ các thiết bị khác",
+ "devices": "Thiết bị",
+ "select": "Chọn",
+ "connect_client_alert": "Bạn đang được điều khiển bởi {client}",
+ "this_device": "Thiết bị này",
+ "remote": "Từ xa"
}
\ No newline at end of file
diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb
index 506661f0..da5254a3 100644
--- a/lib/l10n/app_zh.arb
+++ b/lib/l10n/app_zh.arb
@@ -313,5 +313,12 @@
"help_project_grow_description": "Spotube是一个开源项目。您可以通过为项目做出贡献、报告错误或建议新功能来帮助该项目成长。",
"contribute_on_github": "在GitHub上做出贡献",
"donate_on_open_collective": "在Open Collective上捐款",
- "browse_anonymously": "匿名浏览"
+ "browse_anonymously": "匿名浏览",
+ "enable_connect": "启用连接",
+ "enable_connect_description": "从其他设备控制Spotube",
+ "devices": "设备",
+ "select": "选择",
+ "connect_client_alert": "您正在被 {client} 控制",
+ "this_device": "此设备",
+ "remote": "远程"
}
\ No newline at end of file
diff --git a/lib/l10n/l10n.dart b/lib/l10n/l10n.dart
index e584d2be..ef3685fa 100644
--- a/lib/l10n/l10n.dart
+++ b/lib/l10n/l10n.dart
@@ -12,6 +12,7 @@
/// doannc2212@github => Vietnamese
/// sappho192@github => Korean
/// watchakorn-18k@github => Thai
+/// Microsoft Copilot, Tutislav@github => Czech
library l10n;
@@ -23,6 +24,7 @@ class L10n {
const Locale('ar', 'SA'),
const Locale('bn', 'BD'),
const Locale('ca', 'AD'),
+ const Locale('cs', 'CZ'),
const Locale('de', 'GE'),
const Locale('es', 'ES'),
const Locale('fa', 'IR'),
diff --git a/lib/main.dart b/lib/main.dart
index 0bb72932..7123b0d0 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -4,11 +4,11 @@ import 'package:device_preview/device_preview.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
-import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:hive/hive.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:local_notifier/local_notifier.dart';
import 'package:media_kit/media_kit.dart';
import 'package:metadata_god/metadata_god.dart';
import 'package:shared_preferences/shared_preferences.dart';
@@ -19,6 +19,7 @@ import 'package:spotube/hooks/configurators/use_close_behavior.dart';
import 'package:spotube/hooks/configurators/use_deep_linking.dart';
import 'package:spotube/hooks/configurators/use_disable_battery_optimizations.dart';
import 'package:spotube/hooks/configurators/use_get_storage_perms.dart';
+import 'package:spotube/provider/tray_manager/tray_manager.dart';
import 'package:spotube/l10n/l10n.dart';
import 'package:spotube/models/logger.dart';
import 'package:spotube/models/skip_segment.dart';
@@ -31,15 +32,17 @@ import 'package:spotube/provider/user_preferences/user_preferences_provider.dart
import 'package:spotube/services/audio_player/audio_player.dart';
import 'package:spotube/services/cli/cli.dart';
import 'package:spotube/services/kv_store/kv_store.dart';
+import 'package:spotube/services/wm_tools/wm_tools.dart';
import 'package:spotube/themes/theme.dart';
import 'package:spotube/utils/persisted_state_notifier.dart';
+import 'package:spotube/utils/platform.dart';
import 'package:system_theme/system_theme.dart';
import 'package:path_provider/path_provider.dart';
-import 'package:spotube/hooks/configurators/use_init_sys_tray.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_native_splash/flutter_native_splash.dart';
import 'package:flutter_displaymode/flutter_displaymode.dart';
import 'package:timezone/data/latest.dart' as tz;
+import 'package:window_manager/window_manager.dart';
Future main(List rawArgs) async {
final arguments = await startCLI(rawArgs);
@@ -55,12 +58,12 @@ Future main(List rawArgs) async {
MediaKit.ensureInitialized();
// force High Refresh Rate on some Android devices (like One Plus)
- if (DesktopTools.platform.isAndroid) {
+ if (kIsAndroid) {
await FlutterDisplayMode.setHighRefreshRate();
}
- if (DesktopTools.platform.isDesktop) {
- await DesktopTools.window.setPreventClose(true);
+ if (kIsDesktop) {
+ await windowManager.setPreventClose(true);
}
await SystemTheme.accentColor.load();
@@ -69,7 +72,7 @@ Future main(List rawArgs) async {
MetadataGod.initialize();
}
- if (DesktopTools.platform.isWindows || DesktopTools.platform.isLinux) {
+ if (kIsWindows || kIsLinux) {
DiscordRPC.initialize();
}
@@ -101,14 +104,10 @@ Future main(List rawArgs) async {
path: hiveCacheDir,
);
- await DesktopTools.ensureInitialized(
- DesktopWindowOptions(
- hideTitleBar: true,
- title: "Spotube",
- backgroundColor: Colors.transparent,
- minimumSize: const Size(300, 700),
- ),
- );
+ if (kIsDesktop) {
+ await localNotifier.setup(appName: "Spotube");
+ await WindowManagerTools.initialize();
+ }
Catcher2(
enableLogger: arguments["verbose"],
@@ -189,9 +188,9 @@ class SpotubeState extends ConsumerState {
ref.listen(playbackServerProvider, (_, __) {});
ref.listen(connectServerProvider, (_, __) {});
ref.listen(connectClientsProvider, (_, __) {});
+ ref.listen(trayManagerProvider, (_, __) {});
useDisableBatteryOptimizations();
- useInitSysTray(ref);
useDeepLinking(ref);
useCloseBehavior(ref);
useGetStoragePermissions(ref);
@@ -233,9 +232,7 @@ class SpotubeState extends ConsumerState {
builder: (context, child) {
return DevicePreview.appBuilder(
context,
- DesktopTools.platform.isDesktop && !DesktopTools.platform.isMacOS
- ? DragToResizeArea(child: child!)
- : child,
+ kIsDesktop && !kIsMacOS ? DragToResizeArea(child: child!) : child,
);
},
themeMode: themeMode,
diff --git a/lib/models/connect/connect.freezed.dart b/lib/models/connect/connect.freezed.dart
index dcbd783d..face800e 100644
--- a/lib/models/connect/connect.freezed.dart
+++ b/lib/models/connect/connect.freezed.dart
@@ -12,7 +12,7 @@ part of 'connect.dart';
T _$identity(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
- 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
+ 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
WebSocketLoadEventData _$WebSocketLoadEventDataFromJson(
Map json) {
diff --git a/lib/models/spotify/home_feed.freezed.dart b/lib/models/spotify/home_feed.freezed.dart
index 97c4ffc7..c2bb2aba 100644
--- a/lib/models/spotify/home_feed.freezed.dart
+++ b/lib/models/spotify/home_feed.freezed.dart
@@ -12,7 +12,7 @@ part of 'home_feed.dart';
T _$identity(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
- 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
+ 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
SpotifySectionPlaylist _$SpotifySectionPlaylistFromJson(
Map json) {
diff --git a/lib/models/spotify/recommendation_seeds.freezed.dart b/lib/models/spotify/recommendation_seeds.freezed.dart
index 4cfcce12..adf4aab8 100644
--- a/lib/models/spotify/recommendation_seeds.freezed.dart
+++ b/lib/models/spotify/recommendation_seeds.freezed.dart
@@ -12,7 +12,7 @@ part of 'recommendation_seeds.dart';
T _$identity(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
- 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
+ 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
/// @nodoc
mixin _$GeneratePlaylistProviderInput {
diff --git a/lib/pages/connect/connect.dart b/lib/pages/connect/connect.dart
index 170a0c72..cbdb446e 100644
--- a/lib/pages/connect/connect.dart
+++ b/lib/pages/connect/connect.dart
@@ -23,6 +23,7 @@ class ConnectPage extends HookConsumerWidget {
appBar: PageWindowTitleBar(
automaticallyImplyLeading: true,
title: Text(context.l10n.devices),
+ titleSpacing: 0,
),
body: ListTileTheme(
shape: RoundedRectangleBorder(
diff --git a/lib/pages/home/feed/feed_section.dart b/lib/pages/home/feed/feed_section.dart
index 40ac2482..c945251c 100644
--- a/lib/pages/home/feed/feed_section.dart
+++ b/lib/pages/home/feed/feed_section.dart
@@ -54,6 +54,11 @@ class HomeFeedSectionPage extends HookConsumerWidget {
);
},
),
+ const SliverToBoxAdapter(
+ child: SafeArea(
+ child: SizedBox(),
+ ),
+ ),
],
),
),
diff --git a/lib/pages/home/genres/genre_playlists.dart b/lib/pages/home/genres/genre_playlists.dart
index d80b4513..ca4e7238 100644
--- a/lib/pages/home/genres/genre_playlists.dart
+++ b/lib/pages/home/genres/genre_playlists.dart
@@ -12,7 +12,7 @@ import 'package:spotube/components/shared/waypoint.dart';
import 'package:spotube/extensions/constrains.dart';
import 'package:spotube/provider/spotify/spotify.dart';
import 'package:collection/collection.dart';
-import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
+import 'package:spotube/utils/platform.dart';
class GenrePlaylistsPage extends HookConsumerWidget {
final Category category;
@@ -27,7 +27,7 @@ class GenrePlaylistsPage extends HookConsumerWidget {
final scrollController = useScrollController();
return Scaffold(
- appBar: DesktopTools.platform.isDesktop
+ appBar: kIsDesktop
? const PageWindowTitleBar(
leading: BackButton(color: Colors.white),
backgroundColor: Colors.transparent,
@@ -53,12 +53,12 @@ class GenrePlaylistsPage extends HookConsumerWidget {
controller: scrollController,
slivers: [
SliverAppBar(
- automaticallyImplyLeading: DesktopTools.platform.isMobile,
+ automaticallyImplyLeading: kIsMobile,
expandedHeight: mediaQuery.mdAndDown ? 200 : 150,
title: const Text(""),
backgroundColor: Colors.transparent,
flexibleSpace: FlexibleSpaceBar(
- centerTitle: DesktopTools.platform.isDesktop,
+ centerTitle: kIsDesktop,
title: Text(
category.name!,
style: Theme.of(context).textTheme.headlineMedium?.copyWith(
diff --git a/lib/pages/home/genres/genres.dart b/lib/pages/home/genres/genres.dart
index a981cbe7..291ce737 100644
--- a/lib/pages/home/genres/genres.dart
+++ b/lib/pages/home/genres/genres.dart
@@ -26,6 +26,7 @@ class GenrePage extends HookConsumerWidget {
appBar: PageWindowTitleBar(
title: Text(context.l10n.explore_genres),
automaticallyImplyLeading: true,
+ titleSpacing: 0,
),
body: SafeArea(
top: false,
diff --git a/lib/pages/home/home.dart b/lib/pages/home/home.dart
index e37898a8..a4a71146 100644
--- a/lib/pages/home/home.dart
+++ b/lib/pages/home/home.dart
@@ -1,8 +1,8 @@
import 'package:flutter/material.dart';
-import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:gap/gap.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:spotube/collections/assets.gen.dart';
import 'package:spotube/components/connect/connect_device.dart';
import 'package:spotube/components/home/sections/featured.dart';
import 'package:spotube/components/home/sections/feed.dart';
@@ -14,6 +14,7 @@ import 'package:spotube/components/shared/image/universal_image.dart';
import 'package:spotube/components/shared/page_window_title_bar.dart';
import 'package:spotube/extensions/constrains.dart';
import 'package:spotube/extensions/image.dart';
+import 'package:spotube/provider/authentication_provider.dart';
import 'package:spotube/provider/spotify/spotify.dart';
import 'package:spotube/utils/platform.dart';
import 'package:spotube/utils/service_utils.dart';
@@ -29,19 +30,26 @@ class HomePage extends HookConsumerWidget {
return SafeArea(
bottom: false,
child: Scaffold(
+ appBar: kIsMobile || kIsMacOS ? null : const PageWindowTitleBar(),
body: CustomScrollView(
controller: controller,
slivers: [
if (mediaQuery.mdAndDown)
- PageWindowTitleBar.sliver(
- pinned: DesktopTools.platform.isDesktop,
+ SliverAppBar(
+ floating: true,
+ title: Assets.spotubeLogoPng.image(height: 45),
actions: [
const ConnectDeviceButton(),
const Gap(10),
Consumer(builder: (context, ref, _) {
+ final auth = ref.watch(authenticationProvider);
final me = ref.watch(meProvider);
final meData = me.asData?.value;
+ if (auth == null) {
+ return const SizedBox();
+ }
+
return IconButton(
icon: CircleAvatar(
backgroundImage: UniversalImage.imageProvider(
diff --git a/lib/pages/lyrics/mini_lyrics.dart b/lib/pages/lyrics/mini_lyrics.dart
index 1e4d4641..6d6f75a9 100644
--- a/lib/pages/lyrics/mini_lyrics.dart
+++ b/lib/pages/lyrics/mini_lyrics.dart
@@ -1,5 +1,4 @@
import 'package:flutter/material.dart';
-import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:gap/gap.dart';
import 'package:go_router/go_router.dart';
@@ -18,6 +17,7 @@ import 'package:spotube/pages/lyrics/synced_lyrics.dart';
import 'package:spotube/provider/authentication_provider.dart';
import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart';
import 'package:spotube/utils/platform.dart';
+import 'package:window_manager/window_manager.dart';
class MiniLyricsPage extends HookConsumerWidget {
final Size prevSize;
@@ -36,9 +36,11 @@ class MiniLyricsPage extends HookConsumerWidget {
final showLyrics = useState(true);
useEffect(() {
- WidgetsBinding.instance.addPostFrameCallback((_) async {
- wasMaximized.value = await DesktopTools.window.isMaximized();
- });
+ if (kIsDesktop) {
+ WidgetsBinding.instance.addPostFrameCallback((_) async {
+ wasMaximized.value = await windowManager.isMaximized();
+ });
+ }
return null;
}, []);
@@ -112,11 +114,13 @@ class MiniLyricsPage extends HookConsumerWidget {
areaActive.value = true;
hoverMode.value = false;
- await DesktopTools.window.setSize(
- showLyrics.value
- ? const Size(400, 500)
- : const Size(400, 150),
- );
+ if (kIsDesktop) {
+ await windowManager.setSize(
+ showLyrics.value
+ ? const Size(400, 500)
+ : const Size(400, 150),
+ );
+ }
},
),
IconButton(
@@ -135,33 +139,34 @@ class MiniLyricsPage extends HookConsumerWidget {
hoverMode.value = !hoverMode.value;
},
),
- FutureBuilder(
- future: DesktopTools.window.isAlwaysOnTop(),
- builder: (context, snapshot) {
- return IconButton(
- tooltip: context.l10n.always_on_top,
- icon: Icon(
- snapshot.data == true
- ? SpotubeIcons.pinOn
- : SpotubeIcons.pinOff,
- ),
- style: ButtonStyle(
- foregroundColor: snapshot.data == true
- ? MaterialStateProperty.all(
- theme.colorScheme.primary)
- : null,
- ),
- onPressed: snapshot.data == null
- ? null
- : () async {
- await DesktopTools.window.setAlwaysOnTop(
- snapshot.data == true ? false : true,
- );
- update();
- },
- );
- },
- ),
+ if (kIsDesktop)
+ FutureBuilder(
+ future: windowManager.isAlwaysOnTop(),
+ builder: (context, snapshot) {
+ return IconButton(
+ tooltip: context.l10n.always_on_top,
+ icon: Icon(
+ snapshot.data == true
+ ? SpotubeIcons.pinOn
+ : SpotubeIcons.pinOff,
+ ),
+ style: ButtonStyle(
+ foregroundColor: snapshot.data == true
+ ? MaterialStateProperty.all(
+ theme.colorScheme.primary)
+ : null,
+ ),
+ onPressed: snapshot.data == null
+ ? null
+ : () async {
+ await windowManager.setAlwaysOnTop(
+ snapshot.data == true ? false : true,
+ );
+ update();
+ },
+ );
+ },
+ ),
],
),
),
@@ -243,19 +248,20 @@ class MiniLyricsPage extends HookConsumerWidget {
tooltip: context.l10n.exit_mini_player,
icon: const Icon(SpotubeIcons.maximize),
onPressed: () async {
+ if (!kIsDesktop) return;
+
try {
- await DesktopTools.window
+ await windowManager
.setMinimumSize(const Size(300, 700));
- await DesktopTools.window.setAlwaysOnTop(false);
+ await windowManager.setAlwaysOnTop(false);
if (wasMaximized.value) {
- await DesktopTools.window.maximize();
+ await windowManager.maximize();
} else {
- await DesktopTools.window.setSize(prevSize);
+ await windowManager.setSize(prevSize);
}
- await DesktopTools.window
- .setAlignment(Alignment.center);
+ await windowManager.setAlignment(Alignment.center);
if (!kIsLinux) {
- await DesktopTools.window.setHasShadow(true);
+ await windowManager.setHasShadow(true);
}
await Future.delayed(
const Duration(milliseconds: 200));
diff --git a/lib/pages/root/root_app.dart b/lib/pages/root/root_app.dart
index 56ea43a6..f3ed6571 100644
--- a/lib/pages/root/root_app.dart
+++ b/lib/pages/root/root_app.dart
@@ -2,7 +2,6 @@ import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
-import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
@@ -21,6 +20,7 @@ import 'package:spotube/provider/download_manager_provider.dart';
import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart';
import 'package:spotube/services/connectivity_adapter.dart';
import 'package:spotube/utils/persisted_state_notifier.dart';
+import 'package:spotube/utils/platform.dart';
const rootPaths = {
"/": 0,
@@ -38,7 +38,6 @@ class RootApp extends HookConsumerWidget {
@override
Widget build(BuildContext context, ref) {
- final isMounted = useIsMounted();
final showingDialogCompleter = useRef(Completer()..complete());
final downloader = ref.watch(downloadManagerProvider);
final scaffoldMessenger = ScaffoldMessenger.of(context);
@@ -129,7 +128,7 @@ class RootApp extends HookConsumerWidget {
useEffect(() {
downloader.onFileExists = (track) async {
- if (!isMounted()) return false;
+ if (!context.mounted) return false;
if (!showingDialogCompleter.value.isCompleted) {
await showingDialogCompleter.value.future;
@@ -207,7 +206,7 @@ class RootApp extends HookConsumerWidget {
),
extendBody: true,
drawerScrimColor: Colors.transparent,
- endDrawer: DesktopTools.platform.isDesktop
+ endDrawer: kIsDesktop
? Container(
constraints: const BoxConstraints(maxWidth: 800),
decoration: BoxDecoration(
diff --git a/lib/pages/search/sections/tracks.dart b/lib/pages/search/sections/tracks.dart
index 48dabc13..7fb58759 100644
--- a/lib/pages/search/sections/tracks.dart
+++ b/lib/pages/search/sections/tracks.dart
@@ -113,7 +113,7 @@ class SearchTracksSection extends HookConsumerWidget {
child: TextButton(
onPressed: searchTrack.isLoadingNextPage
? null
- : () => searchTrackNotifier.fetchMore,
+ : searchTrackNotifier.fetchMore,
child: searchTrack.isLoadingNextPage
? const CircularProgressIndicator()
: Text(context.l10n.load_more),
diff --git a/lib/pages/settings/sections/desktop.dart b/lib/pages/settings/sections/desktop.dart
index 4e4408d9..56306868 100644
--- a/lib/pages/settings/sections/desktop.dart
+++ b/lib/pages/settings/sections/desktop.dart
@@ -1,5 +1,4 @@
import 'package:flutter/material.dart';
-import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
import 'package:gap/gap.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:spotube/collections/spotube_icons.dart';
@@ -8,6 +7,7 @@ import 'package:spotube/components/shared/adaptive/adaptive_select_tile.dart';
import 'package:spotube/extensions/context.dart';
import 'package:spotube/provider/user_preferences/user_preferences_provider.dart';
import 'package:spotube/provider/user_preferences/user_preferences_state.dart';
+import 'package:spotube/utils/platform.dart';
class SettingsDesktopSection extends HookConsumerWidget {
const SettingsDesktopSection({super.key});
@@ -53,7 +53,7 @@ class SettingsDesktopSection extends HookConsumerWidget {
value: preferences.systemTitleBar,
onChanged: preferencesNotifier.setSystemTitleBar,
),
- if (!DesktopTools.platform.isMacOS)
+ if (!kIsMacOS)
SwitchListTile(
secondary: const Icon(SpotubeIcons.discord),
title: Text(context.l10n.discord_rich_presence),
diff --git a/lib/pages/settings/sections/downloads.dart b/lib/pages/settings/sections/downloads.dart
index 1f25028e..76ef8e3e 100644
--- a/lib/pages/settings/sections/downloads.dart
+++ b/lib/pages/settings/sections/downloads.dart
@@ -1,13 +1,13 @@
import 'package:file_picker/file_picker.dart';
import 'package:file_selector/file_selector.dart';
import 'package:flutter/material.dart';
-import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:spotube/collections/spotube_icons.dart';
import 'package:spotube/components/settings/section_card_with_heading.dart';
import 'package:spotube/extensions/context.dart';
import 'package:spotube/provider/user_preferences/user_preferences_provider.dart';
+import 'package:spotube/utils/platform.dart';
class SettingsDownloadsSection extends HookConsumerWidget {
const SettingsDownloadsSection({super.key});
@@ -18,7 +18,7 @@ class SettingsDownloadsSection extends HookConsumerWidget {
final preferences = ref.watch(userPreferencesProvider);
final pickDownloadLocation = useCallback(() async {
- if (DesktopTools.platform.isMobile || DesktopTools.platform.isMacOS) {
+ if (kIsMobile || kIsMacOS) {
final dirStr = await FilePicker.platform.getDirectoryPath(
initialDirectory: preferences.downloadLocation,
);
diff --git a/lib/pages/settings/settings.dart b/lib/pages/settings/settings.dart
index d2a75057..d293518d 100644
--- a/lib/pages/settings/settings.dart
+++ b/lib/pages/settings/settings.dart
@@ -1,6 +1,5 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
-import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:spotube/components/shared/page_window_title_bar.dart';
@@ -14,6 +13,7 @@ import 'package:spotube/pages/settings/sections/downloads.dart';
import 'package:spotube/pages/settings/sections/language_region.dart';
import 'package:spotube/pages/settings/sections/playback.dart';
import 'package:spotube/provider/user_preferences/user_preferences_provider.dart';
+import 'package:spotube/utils/platform.dart';
class SettingsPage extends HookConsumerWidget {
const SettingsPage({super.key});
@@ -45,8 +45,7 @@ class SettingsPage extends HookConsumerWidget {
const SettingsAppearanceSection(),
const SettingsPlaybackSection(),
const SettingsDownloadsSection(),
- if (DesktopTools.platform.isDesktop)
- const SettingsDesktopSection(),
+ if (kIsDesktop) const SettingsDesktopSection(),
if (!kIsWeb) const SettingsDevelopersSection(),
const SettingsAboutSection(),
Center(
diff --git a/lib/provider/discord_provider.dart b/lib/provider/discord_provider.dart
index ca8eecfa..f90db54a 100644
--- a/lib/provider/discord_provider.dart
+++ b/lib/provider/discord_provider.dart
@@ -1,21 +1,19 @@
import 'package:dart_discord_rpc/dart_discord_rpc.dart';
import 'package:flutter/foundation.dart';
-import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:spotify/spotify.dart';
import 'package:spotube/collections/env.dart';
import 'package:spotube/extensions/artist_simple.dart';
import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart';
import 'package:spotube/provider/user_preferences/user_preferences_provider.dart';
+import 'package:spotube/utils/platform.dart';
class Discord extends ChangeNotifier {
final DiscordRPC? discordRPC;
final bool isEnabled;
Discord(this.isEnabled)
- : discordRPC = (DesktopTools.platform.isWindows ||
- DesktopTools.platform.isLinux) &&
- isEnabled
+ : discordRPC = (kIsWindows || kIsLinux) && isEnabled
? DiscordRPC(applicationId: Env.discordAppId)
: null {
discordRPC?.start(autoRegister: true);
diff --git a/lib/provider/tray_manager/tray_manager.dart b/lib/provider/tray_manager/tray_manager.dart
new file mode 100644
index 00000000..2145cbef
--- /dev/null
+++ b/lib/provider/tray_manager/tray_manager.dart
@@ -0,0 +1,79 @@
+import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:spotube/provider/tray_manager/tray_menu.dart';
+import 'package:spotube/provider/user_preferences/user_preferences_provider.dart';
+import 'package:spotube/utils/platform.dart';
+import 'package:tray_manager/tray_manager.dart';
+import 'package:window_manager/window_manager.dart';
+
+class SystemTrayManager with TrayListener {
+ final Ref ref;
+ final bool enabled;
+
+ SystemTrayManager(
+ this.ref, {
+ required this.enabled,
+ }) {
+ initialize();
+ }
+
+ Future initialize() async {
+ if (!kIsDesktop) return;
+
+ if (enabled) {
+ await trayManager.setIcon(
+ kIsWindows
+ ? 'assets/spotube-logo.ico'
+ : kIsFlatpak
+ ? 'com.github.KRTirtho.Spotube.png'
+ : 'assets/spotube-logo.png',
+ );
+ trayManager.addListener(this);
+ } else {
+ await trayManager.destroy();
+ }
+ }
+
+ void dispose() {
+ trayManager.removeListener(this);
+ }
+
+ @override
+ onTrayIconMouseDown() {
+ if (kIsWindows) {
+ windowManager.show();
+ } else {
+ trayManager.popUpContextMenu();
+ }
+ }
+
+ @override
+ onTrayIconRightMouseDown() {
+ if (!kIsWindows) {
+ windowManager.show();
+ } else {
+ trayManager.popUpContextMenu();
+ }
+ }
+}
+
+final trayManagerProvider = Provider(
+ (ref) {
+ final enabled = ref.watch(
+ userPreferencesProvider.select((s) => s.showSystemTrayIcon),
+ );
+
+ ref.listen(trayMenuProvider, (_, menu) {
+ if (!enabled || !kIsDesktop) return;
+ trayManager.setContextMenu(menu);
+ });
+
+ final manager = SystemTrayManager(
+ ref,
+ enabled: enabled,
+ );
+
+ ref.onDispose(manager.dispose);
+
+ return manager;
+ },
+);
diff --git a/lib/provider/tray_manager/tray_menu.dart b/lib/provider/tray_manager/tray_menu.dart
new file mode 100644
index 00000000..cb793707
--- /dev/null
+++ b/lib/provider/tray_manager/tray_menu.dart
@@ -0,0 +1,108 @@
+import 'dart:io';
+
+import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart';
+import 'package:spotube/services/audio_player/audio_player.dart';
+import 'package:spotube/services/audio_player/loop_mode.dart';
+import 'package:tray_manager/tray_manager.dart';
+import 'package:window_manager/window_manager.dart';
+
+final audioPlayerLoopMode = StreamProvider((ref) {
+ return audioPlayer.loopModeStream;
+});
+
+final audioPlayerShuffleMode = StreamProvider((ref) {
+ return audioPlayer.shuffledStream;
+});
+final audioPlayerPlaying = StreamProvider((ref) {
+ return audioPlayer.playingStream;
+});
+
+final trayMenuProvider = Provider((ref) {
+ final playlistNotifier = ref.watch(proxyPlaylistProvider.notifier);
+ final isPlaybackPlaying =
+ ref.watch(proxyPlaylistProvider.select((s) => s.activeTrack != null));
+ final isLoopOne =
+ ref.watch(audioPlayerLoopMode).asData?.value == PlaybackLoopMode.one;
+ final isShuffled = ref.watch(audioPlayerShuffleMode).asData?.value ?? false;
+ final isPlaying = ref.watch(audioPlayerPlaying).asData?.value ?? false;
+
+ return Menu(
+ items: [
+ MenuItem(
+ label: "Show/Hide Window",
+ onClick: (menuItem) async {
+ if (await windowManager.isVisible()) {
+ await windowManager.hide();
+ } else {
+ await windowManager.focus();
+ await windowManager.show();
+ }
+ },
+ ),
+ MenuItem.separator(),
+ MenuItem(
+ label: isPlaying ? "Pause" : "Play",
+ disabled: !isPlaybackPlaying,
+ onClick: (menuItem) async {
+ if (audioPlayer.isPlaying) {
+ await audioPlayer.pause();
+ } else {
+ await audioPlayer.resume();
+ }
+ },
+ ),
+ MenuItem(
+ label: "Next",
+ disabled: !isPlaybackPlaying,
+ onClick: (menuItem) {
+ playlistNotifier.next();
+ },
+ ),
+ MenuItem(
+ label: "Previous",
+ disabled: !isPlaybackPlaying,
+ onClick: (menuItem) {
+ playlistNotifier.previous();
+ },
+ ),
+ MenuItem.submenu(
+ label: "Playback",
+ submenu: Menu(
+ items: [
+ MenuItem(
+ label: "Repeat",
+ checked: isLoopOne,
+ onClick: (menuItem) {
+ audioPlayer.setLoopMode(
+ isLoopOne ? PlaybackLoopMode.none : PlaybackLoopMode.one,
+ );
+ },
+ ),
+ MenuItem(
+ label: "Shuffle",
+ checked: isShuffled,
+ onClick: (menuItem) {
+ audioPlayer.setShuffle(!isShuffled);
+ },
+ ),
+ MenuItem.separator(),
+ MenuItem(
+ label: "Stop",
+ onClick: (menuItem) {
+ playlistNotifier.stop();
+ },
+ ),
+ ],
+ ),
+ ),
+ MenuItem.separator(),
+ MenuItem(
+ label: "Quit",
+ onClick: (menuItem) {
+ exit(0);
+ },
+ ),
+ ],
+ );
+});
diff --git a/lib/provider/user_preferences/user_preferences_provider.dart b/lib/provider/user_preferences/user_preferences_provider.dart
index a1e247b2..a537038e 100644
--- a/lib/provider/user_preferences/user_preferences_provider.dart
+++ b/lib/provider/user_preferences/user_preferences_provider.dart
@@ -1,7 +1,6 @@
import 'dart:async';
import 'package:flutter/material.dart';
-import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:path_provider/path_provider.dart';
import 'package:spotify/spotify.dart';
@@ -15,6 +14,7 @@ import 'package:spotube/services/sourced_track/enums.dart';
import 'package:spotube/utils/persisted_state_notifier.dart';
import 'package:spotube/utils/platform.dart';
import 'package:path/path.dart' as path;
+import 'package:window_manager/window_manager.dart';
class UserPreferencesNotifier extends PersistedStateNotifier {
final Ref ref;
@@ -103,8 +103,8 @@ class UserPreferencesNotifier extends PersistedStateNotifier {
void setSystemTitleBar(bool isSystemTitleBar) {
state = state.copyWith(systemTitleBar: isSystemTitleBar);
- if (DesktopTools.platform.isDesktop) {
- DesktopTools.window.setTitleBarStyle(
+ if (kIsDesktop) {
+ windowManager.setTitleBarStyle(
isSystemTitleBar ? TitleBarStyle.normal : TitleBarStyle.hidden,
);
}
@@ -151,8 +151,8 @@ class UserPreferencesNotifier extends PersistedStateNotifier {
);
}
- if (DesktopTools.platform.isDesktop) {
- await DesktopTools.window.setTitleBarStyle(
+ if (kIsDesktop) {
+ await windowManager.setTitleBarStyle(
state.systemTitleBar ? TitleBarStyle.normal : TitleBarStyle.hidden,
);
}
diff --git a/lib/provider/user_preferences/user_preferences_state.dart b/lib/provider/user_preferences/user_preferences_state.dart
index e35c73b5..67eb18a2 100644
--- a/lib/provider/user_preferences/user_preferences_state.dart
+++ b/lib/provider/user_preferences/user_preferences_state.dart
@@ -62,10 +62,10 @@ class UserPreferences with _$UserPreferences {
@Default(false) bool amoledDarkTheme,
@Default(true) bool checkUpdate,
@Default(false) bool normalizeAudio,
- @Default(true) bool showSystemTrayIcon,
+ @Default(false) bool showSystemTrayIcon,
@Default(false) bool skipNonMusic,
@Default(false) bool systemTitleBar,
- @Default(CloseBehavior.minimizeToTray) CloseBehavior closeBehavior,
+ @Default(CloseBehavior.close) CloseBehavior closeBehavior,
@Default(SpotubeColor(0xFF2196F3, name: "Blue"))
@JsonKey(
fromJson: UserPreferences._accentColorSchemeFromJson,
diff --git a/lib/provider/user_preferences/user_preferences_state.freezed.dart b/lib/provider/user_preferences/user_preferences_state.freezed.dart
index a5b076bb..94015d37 100644
--- a/lib/provider/user_preferences/user_preferences_state.freezed.dart
+++ b/lib/provider/user_preferences/user_preferences_state.freezed.dart
@@ -12,7 +12,7 @@ part of 'user_preferences_state.dart';
T _$identity(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
- 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
+ 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
UserPreferences _$UserPreferencesFromJson(Map json) {
return _UserPreferences.fromJson(json);
@@ -415,10 +415,10 @@ class _$UserPreferencesImpl implements _UserPreferences {
this.amoledDarkTheme = false,
this.checkUpdate = true,
this.normalizeAudio = false,
- this.showSystemTrayIcon = true,
+ this.showSystemTrayIcon = false,
this.skipNonMusic = false,
this.systemTitleBar = false,
- this.closeBehavior = CloseBehavior.minimizeToTray,
+ this.closeBehavior = CloseBehavior.close,
@JsonKey(
fromJson: UserPreferences._accentColorSchemeFromJson,
toJson: UserPreferences._accentColorSchemeToJson,
diff --git a/lib/provider/user_preferences/user_preferences_state.g.dart b/lib/provider/user_preferences/user_preferences_state.g.dart
index 8bdd12cc..930b1dd1 100644
--- a/lib/provider/user_preferences/user_preferences_state.g.dart
+++ b/lib/provider/user_preferences/user_preferences_state.g.dart
@@ -16,12 +16,12 @@ _$UserPreferencesImpl _$$UserPreferencesImplFromJson(
amoledDarkTheme: json['amoledDarkTheme'] as bool? ?? false,
checkUpdate: json['checkUpdate'] as bool? ?? true,
normalizeAudio: json['normalizeAudio'] as bool? ?? false,
- showSystemTrayIcon: json['showSystemTrayIcon'] as bool? ?? true,
+ showSystemTrayIcon: json['showSystemTrayIcon'] as bool? ?? false,
skipNonMusic: json['skipNonMusic'] as bool? ?? false,
systemTitleBar: json['systemTitleBar'] as bool? ?? false,
closeBehavior:
$enumDecodeNullable(_$CloseBehaviorEnumMap, json['closeBehavior']) ??
- CloseBehavior.minimizeToTray,
+ CloseBehavior.close,
accentColorScheme: UserPreferences._accentColorSchemeReadValue(
json, 'accentColorScheme') ==
null
diff --git a/lib/services/audio_player/audio_player.dart b/lib/services/audio_player/audio_player.dart
index a81c6c95..92de192b 100644
--- a/lib/services/audio_player/audio_player.dart
+++ b/lib/services/audio_player/audio_player.dart
@@ -101,7 +101,7 @@ abstract class AudioPlayerInterface {
return _mkPlayer.state.completed;
}
- Future get isShuffled async {
+ bool get isShuffled {
return _mkPlayer.shuffled;
}
diff --git a/lib/services/audio_player/custom_player.dart b/lib/services/audio_player/custom_player.dart
index d273519e..e32a0d14 100644
--- a/lib/services/audio_player/custom_player.dart
+++ b/lib/services/audio_player/custom_player.dart
@@ -1,5 +1,4 @@
import 'dart:async';
-import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
import 'package:catcher_2/catcher_2.dart';
import 'package:media_kit/media_kit.dart';
import 'package:flutter_broadcasts/flutter_broadcasts.dart';
@@ -7,6 +6,7 @@ import 'package:package_info_plus/package_info_plus.dart';
import 'package:audio_session/audio_session.dart';
// ignore: implementation_imports
import 'package:spotube/services/audio_player/playback_state.dart';
+import 'package:spotube/utils/platform.dart';
/// MediaKit [Player] by default doesn't have a state stream.
/// This class adds a state stream to the [Player] class.
@@ -54,7 +54,7 @@ class CustomPlayer extends Player {
PackageInfo.fromPlatform().then((packageInfo) {
_packageName = packageInfo.packageName;
});
- if (DesktopTools.platform.isAndroid) {
+ if (kIsAndroid) {
_androidAudioManager = AndroidAudioManager();
AudioSession.instance.then((s) async {
_androidAudioSessionId =
@@ -71,7 +71,7 @@ class CustomPlayer extends Player {
}
Future notifyAudioSessionUpdate(bool active) async {
- if (DesktopTools.platform.isAndroid) {
+ if (kIsAndroid) {
sendBroadcast(
BroadcastMessage(
name: active
@@ -106,6 +106,10 @@ class CustomPlayer extends Player {
_shuffled = shuffle;
await super.setShuffle(shuffle);
_shuffleStream.add(shuffle);
+ await Future.delayed(const Duration(milliseconds: 100));
+ if (shuffle) {
+ await move(state.playlist.index, 0);
+ }
}
@override
diff --git a/lib/services/audio_services/audio_services.dart b/lib/services/audio_services/audio_services.dart
index 338427aa..f42d6c4b 100644
--- a/lib/services/audio_services/audio_services.dart
+++ b/lib/services/audio_services/audio_services.dart
@@ -1,5 +1,4 @@
import 'package:audio_service/audio_service.dart';
-import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:spotify/spotify.dart';
import 'package:spotube/extensions/artist_simple.dart';
@@ -8,6 +7,7 @@ import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart';
import 'package:spotube/services/audio_services/mobile_audio_service.dart';
import 'package:spotube/services/audio_services/windows_audio_service.dart';
import 'package:spotube/services/sourced_track/sourced_track.dart';
+import 'package:spotube/utils/platform.dart';
class AudioServices {
final MobileAudioService? mobile;
@@ -19,9 +19,7 @@ class AudioServices {
Ref ref,
ProxyPlaylistNotifier playback,
) async {
- final mobile = DesktopTools.platform.isMobile ||
- DesktopTools.platform.isMacOS ||
- DesktopTools.platform.isLinux
+ final mobile = kIsMobile || kIsMacOS || kIsLinux
? await AudioService.init(
builder: () => MobileAudioService(playback),
config: const AudioServiceConfig(
@@ -31,9 +29,7 @@ class AudioServices {
),
)
: null;
- final smtc = DesktopTools.platform.isWindows
- ? WindowsAudioService(ref, playback)
- : null;
+ final smtc = kIsWindows ? WindowsAudioService(ref, playback) : null;
return AudioServices(
mobile,
diff --git a/lib/services/kv_store/kv_store.dart b/lib/services/kv_store/kv_store.dart
index f94ec4ee..ae62a055 100644
--- a/lib/services/kv_store/kv_store.dart
+++ b/lib/services/kv_store/kv_store.dart
@@ -1,4 +1,7 @@
+import 'dart:convert';
+
import 'package:shared_preferences/shared_preferences.dart';
+import 'package:spotube/services/wm_tools/wm_tools.dart';
abstract class KVStoreService {
static SharedPreferences? _sharedPreferences;
@@ -23,4 +26,21 @@ abstract class KVStoreService {
static Future setRecentSearches(List value) async =>
await sharedPreferences.setStringList('recentSearches', value);
+
+ static WindowSize? get windowSize {
+ final raw = sharedPreferences.getString('windowSize');
+
+ if (raw == null) {
+ return null;
+ }
+ return WindowSize.fromJson(jsonDecode(raw));
+ }
+
+ static Future setWindowSize(WindowSize value) async =>
+ await sharedPreferences.setString(
+ 'windowSize',
+ jsonEncode(
+ value.toJson(),
+ ),
+ );
}
diff --git a/lib/services/song_link/song_link.freezed.dart b/lib/services/song_link/song_link.freezed.dart
index a8230eeb..0a1af8a9 100644
--- a/lib/services/song_link/song_link.freezed.dart
+++ b/lib/services/song_link/song_link.freezed.dart
@@ -12,7 +12,7 @@ part of 'song_link.dart';
T _$identity(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
- 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
+ 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
SongLink _$SongLinkFromJson(Map json) {
return _SongLink.fromJson(json);
diff --git a/lib/services/sourced_track/sources/piped.dart b/lib/services/sourced_track/sources/piped.dart
index 75f83125..8444db53 100644
--- a/lib/services/sourced_track/sources/piped.dart
+++ b/lib/services/sourced_track/sources/piped.dart
@@ -163,7 +163,7 @@ class PipedSourcedTrack extends SourcedTrack {
final PipedSearchResult(items: searchResults) = await pipedClient.search(
query,
preference.searchMode == SearchMode.youtube
- ? PipedFilter.videos
+ ? PipedFilter.video
: PipedFilter.musicSongs,
);
diff --git a/lib/services/wm_tools/wm_tools.dart b/lib/services/wm_tools/wm_tools.dart
new file mode 100644
index 00000000..4572a8b4
--- /dev/null
+++ b/lib/services/wm_tools/wm_tools.dart
@@ -0,0 +1,88 @@
+import 'package:flutter/material.dart';
+import 'package:spotube/services/kv_store/kv_store.dart';
+import 'package:spotube/utils/platform.dart';
+import 'package:window_manager/window_manager.dart';
+
+class WindowSize {
+ final double height;
+ final double width;
+ final bool maximized;
+
+ WindowSize({
+ required this.height,
+ required this.width,
+ required this.maximized,
+ });
+
+ factory WindowSize.fromJson(Map json) => WindowSize(
+ height: json["height"],
+ width: json["width"],
+ maximized: json["maximized"],
+ );
+
+ Map toJson() => {
+ "height": height,
+ "width": width,
+ "maximized": maximized,
+ };
+}
+
+class WindowManagerTools with WidgetsBindingObserver {
+ static WindowManagerTools? _instance;
+ static WindowManagerTools get instance => _instance!;
+
+ WindowManagerTools._();
+
+ static Future initialize() async {
+ await windowManager.ensureInitialized();
+ _instance = WindowManagerTools._();
+ WidgetsBinding.instance.addObserver(instance);
+
+ await windowManager.waitUntilReadyToShow(
+ const WindowOptions(
+ title: "Spotube",
+ backgroundColor: Colors.transparent,
+ minimumSize: Size(300, 700),
+ titleBarStyle: TitleBarStyle.hidden,
+ ),
+ () async {
+ final savedSize = KVStoreService.windowSize;
+ await windowManager.setResizable(true);
+ if (savedSize?.maximized == true &&
+ !(await windowManager.isMaximized())) {
+ await windowManager.maximize();
+ } else if (savedSize != null) {
+ await windowManager.setSize(Size(savedSize.width, savedSize.height));
+ }
+
+ await windowManager.focus();
+ await windowManager.show();
+ },
+ );
+ }
+
+ Size? _prevSize;
+
+ @override
+ void didChangeMetrics() async {
+ super.didChangeMetrics();
+ if (kIsMobile) return;
+ final size = await windowManager.getSize();
+ final windowSameDimension =
+ _prevSize?.width == size.width && _prevSize?.height == size.height;
+
+ if (windowSameDimension || _prevSize == null) {
+ _prevSize = size;
+ return;
+ }
+ final isMaximized = await windowManager.isMaximized();
+ await KVStoreService.setWindowSize(
+ WindowSize(
+ height: size.height,
+ width: size.width,
+ maximized: isMaximized,
+ ),
+ );
+ _prevSize = size;
+ }
+}
diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc
index c69c17c0..6dfdd740 100644
--- a/linux/flutter/generated_plugin_registrant.cc
+++ b/linux/flutter/generated_plugin_registrant.cc
@@ -14,7 +14,7 @@
#include
#include
#include
-#include
+#include
#include
#include
#include
@@ -44,9 +44,9 @@ void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) system_theme_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "SystemThemePlugin");
system_theme_plugin_register_with_registrar(system_theme_registrar);
- g_autoptr(FlPluginRegistrar) system_tray_registrar =
- fl_plugin_registry_get_registrar_for_plugin(registry, "SystemTrayPlugin");
- system_tray_plugin_register_with_registrar(system_tray_registrar);
+ g_autoptr(FlPluginRegistrar) tray_manager_registrar =
+ fl_plugin_registry_get_registrar_for_plugin(registry, "TrayManagerPlugin");
+ tray_manager_plugin_register_with_registrar(tray_manager_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);
diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake
index a4487f4d..93ffd3e9 100644
--- a/linux/flutter/generated_plugins.cmake
+++ b/linux/flutter/generated_plugins.cmake
@@ -11,7 +11,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
media_kit_libs_linux
screen_retriever
system_theme
- system_tray
+ tray_manager
url_launcher_linux
window_manager
window_size
diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift
index a9f6650f..84f39341 100644
--- a/macos/Flutter/GeneratedPluginRegistrant.swift
+++ b/macos/Flutter/GeneratedPluginRegistrant.swift
@@ -21,7 +21,7 @@ import screen_retriever
import shared_preferences_foundation
import sqflite
import system_theme
-import system_tray
+import tray_manager
import url_launcher_macos
import window_manager
import window_size
@@ -37,13 +37,13 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin"))
LocalNotifierPlugin.register(with: registry.registrar(forPlugin: "LocalNotifierPlugin"))
MediaKitLibsMacosAudioPlugin.register(with: registry.registrar(forPlugin: "MediaKitLibsMacosAudioPlugin"))
- FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin"))
+ FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
ScreenRetrieverPlugin.register(with: registry.registrar(forPlugin: "ScreenRetrieverPlugin"))
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
SystemThemePlugin.register(with: registry.registrar(forPlugin: "SystemThemePlugin"))
- SystemTrayPlugin.register(with: registry.registrar(forPlugin: "SystemTrayPlugin"))
+ TrayManagerPlugin.register(with: registry.registrar(forPlugin: "TrayManagerPlugin"))
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
WindowManagerPlugin.register(with: registry.registrar(forPlugin: "WindowManagerPlugin"))
WindowSizePlugin.register(with: registry.registrar(forPlugin: "WindowSizePlugin"))
diff --git a/macos/Podfile.lock b/macos/Podfile.lock
index 317de385..ce2ef233 100644
--- a/macos/Podfile.lock
+++ b/macos/Podfile.lock
@@ -18,9 +18,6 @@ PODS:
- flutter_secure_storage_macos (6.1.1):
- FlutterMacOS
- FlutterMacOS (1.0.0)
- - FMDB (2.7.5):
- - FMDB/standard (= 2.7.5)
- - FMDB/standard (2.7.5)
- local_notifier (0.1.0):
- FlutterMacOS
- media_kit_libs_macos_audio (1.0.4):
@@ -39,12 +36,12 @@ PODS:
- shared_preferences_foundation (0.0.1):
- Flutter
- FlutterMacOS
- - sqflite (0.0.2):
+ - sqflite (0.0.3):
+ - Flutter
- FlutterMacOS
- - FMDB (>= 2.7.5)
- system_theme (0.0.1):
- FlutterMacOS
- - system_tray (0.0.1):
+ - tray_manager (0.0.1):
- FlutterMacOS
- url_launcher_macos (0.0.1):
- FlutterMacOS
@@ -71,16 +68,15 @@ DEPENDENCIES:
- path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`)
- screen_retriever (from `Flutter/ephemeral/.symlinks/plugins/screen_retriever/macos`)
- shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`)
- - sqflite (from `Flutter/ephemeral/.symlinks/plugins/sqflite/macos`)
+ - sqflite (from `Flutter/ephemeral/.symlinks/plugins/sqflite/darwin`)
- system_theme (from `Flutter/ephemeral/.symlinks/plugins/system_theme/macos`)
- - system_tray (from `Flutter/ephemeral/.symlinks/plugins/system_tray/macos`)
+ - tray_manager (from `Flutter/ephemeral/.symlinks/plugins/tray_manager/macos`)
- url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`)
- window_manager (from `Flutter/ephemeral/.symlinks/plugins/window_manager/macos`)
- window_size (from `Flutter/ephemeral/.symlinks/plugins/window_size/macos`)
SPEC REPOS:
trunk:
- - FMDB
- OrderedSet
EXTERNAL SOURCES:
@@ -119,11 +115,11 @@ EXTERNAL SOURCES:
shared_preferences_foundation:
:path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin
sqflite:
- :path: Flutter/ephemeral/.symlinks/plugins/sqflite/macos
+ :path: Flutter/ephemeral/.symlinks/plugins/sqflite/darwin
system_theme:
:path: Flutter/ephemeral/.symlinks/plugins/system_theme/macos
- system_tray:
- :path: Flutter/ephemeral/.symlinks/plugins/system_tray/macos
+ tray_manager:
+ :path: Flutter/ephemeral/.symlinks/plugins/tray_manager/macos
url_launcher_macos:
:path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos
window_manager:
@@ -132,28 +128,27 @@ EXTERNAL SOURCES:
:path: Flutter/ephemeral/.symlinks/plugins/window_size/macos
SPEC CHECKSUMS:
- app_links: 4481ed4d71f384b0c3ae5016f4633aa73d32ff67
+ app_links: 10e0a0ab602ffaf34d142cd4862f29d34b303b2a
audio_service: b88ff778e0e3915efd4cd1a5ad6f0beef0c950a9
audio_session: dea1f41890dbf1718f04a56f1d6150fd50039b72
bonsoir_darwin: e3b8526c42ca46a885142df84229131dfabea842
- device_info_plus: 5401765fde0b8d062a2f8eb65510fb17e77cf07f
+ device_info_plus: ce1b7762849d3ec103d0e0517299f2db7ad60720
file_selector_macos: 468fb6b81fac7c0e88d71317f3eec34c3b008ff9
flutter_inappwebview_macos: 9600c9df9fdb346aaa8933812009f8d94304203d
flutter_secure_storage_macos: d56e2d218c1130b262bef8b4a7d64f88d7f9c9ea
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
- FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
local_notifier: e9506bc66fc70311e8bc7291fb70f743c081e4ff
media_kit_libs_macos_audio: 3871782a4f3f84c77f04d7666c87800a781c24da
media_kit_native_event_loop: 7321675377cb9ae8596a29bddf3a3d2b5e8792c5
metadata_god: eceae399d0020475069a5cebc35943ce8562b5d7
OrderedSet: aaeb196f7fef5a9edf55d89760da9176ad40b93c
- package_info_plus: 02d7a575e80f194102bef286361c6c326e4c29ce
- path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943
+ package_info_plus: fa739dd842b393193c5ca93c26798dff6e3d0e0c
+ path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c
screen_retriever: 59634572a57080243dd1bf715e55b6c54f241a38
- shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126
- sqflite: a5789cceda41d54d23f31d6de539d65bb14100ea
+ shared_preferences_foundation: b4c3b4cddf1c21f02770737f147a3f5da9d39695
+ sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec
system_theme: c7b9f6659a5caa26c9bc2284da096781e9a6fcbc
- system_tray: e53c972838c69589ff2e77d6d3abfd71332f9e5d
+ tray_manager: 9064e219c56d75c476e46b9a21182087930baf90
url_launcher_macos: d2691c7dd33ed713bf3544850a623080ec693d95
window_manager: 3a1844359a6295ab1e47659b1a777e36773cd6e8
window_size: 339dafa0b27a95a62a843042038fa6c3c48de195
diff --git a/pubspec.lock b/pubspec.lock
index 68bad095..ebb6d2c4 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -5,26 +5,26 @@ packages:
dependency: transitive
description:
name: _fe_analyzer_shared
- sha256: ae92f5d747aee634b87f89d9946000c2de774be1d6ac3e58268224348cd0101a
+ sha256: "0b2f2bd91ba804e53a61d757b986f89f1f9eaed5b11e4b2f5a2468d86d6c9fc7"
url: "https://pub.dev"
source: hosted
- version: "61.0.0"
+ version: "67.0.0"
analyzer:
dependency: transitive
description:
name: analyzer
- sha256: ea3d8652bda62982addfd92fdc2d0214e5f82e43325104990d4f4c4a2a313562
+ sha256: "37577842a27e4338429a1cbc32679d508836510b056f1eedf0c8d20e39c1383d"
url: "https://pub.dev"
source: hosted
- version: "5.13.0"
+ version: "6.4.1"
analyzer_plugin:
dependency: transitive
description:
name: analyzer_plugin
- sha256: c1d5f167683de03d5ab6c3b53fc9aeefc5d59476e7810ba7bbddff50c6f4392d
+ sha256: "9661b30b13a685efaee9f02e5d01ed9f2b423bd889d28a304d02d704aee69161"
url: "https://pub.dev"
source: hosted
- version: "0.11.2"
+ version: "0.11.3"
ansicolor:
dependency: transitive
description:
@@ -37,90 +37,26 @@ packages:
dependency: "direct main"
description:
name: app_links
- sha256: "4e392b5eba997df356ca6021f28431ce1cfeb16758699553a94b13add874a3bb"
+ sha256: "42dc15aecf2618ace4ffb74a2e58a50e45cd1b9f2c17c8f0cafe4c297f08c815"
url: "https://pub.dev"
source: hosted
- version: "3.5.0"
- app_package_maker:
- dependency: transitive
- description:
- name: app_package_maker
- sha256: "0dc1949e09a60ec2d0b79b43c5237734e6d03f7a022919bdfe1b4789f4c3bfb0"
- url: "https://pub.dev"
- source: hosted
- version: "0.0.9"
- app_package_maker_aab:
- dependency: transitive
- description:
- name: app_package_maker_aab
- sha256: "44810e77dff3b3b54011270b01a42876e838766d6e85c98f9a33bfe61db51651"
- url: "https://pub.dev"
- source: hosted
- version: "0.0.9"
- app_package_maker_apk:
- dependency: transitive
- description:
- name: app_package_maker_apk
- sha256: "974e639cda26c2e18fffaba18f88797523731f5b5457056b25e92243c9191f61"
- url: "https://pub.dev"
- source: hosted
- version: "0.0.9"
- app_package_maker_deb:
- dependency: transitive
- description:
- name: app_package_maker_deb
- sha256: dcd4047cb67648e53afd61079a8baa3c8ea383668f068e3ce8da841f3728eb29
- url: "https://pub.dev"
- source: hosted
- version: "0.0.9"
- app_package_maker_dmg:
- dependency: transitive
- description:
- name: app_package_maker_dmg
- sha256: e0410a51304f3fff3e3850696c8e56f53f71c990e097f1c325126ebe90d242c4
- url: "https://pub.dev"
- source: hosted
- version: "0.0.9"
- app_package_maker_exe:
- dependency: transitive
- description:
- name: app_package_maker_exe
- sha256: "07e3899a3ae12e8b6cd80efc7281ccca6c9050d2810e0fdc0e7e614cf4bd8a02"
- url: "https://pub.dev"
- source: hosted
- version: "0.0.9"
- app_package_maker_ipa:
- dependency: transitive
- description:
- name: app_package_maker_ipa
- sha256: "1a11498506ba975d02a4715650701981a382a2161c81481911517b50b378cd65"
- url: "https://pub.dev"
- source: hosted
- version: "0.0.9"
- app_package_maker_zip:
- dependency: transitive
- description:
- name: app_package_maker_zip
- sha256: cef07a47c589036a4762fdc9e61b9022f0a2a2a9f69538109a0a952a7e668306
- url: "https://pub.dev"
- source: hosted
- version: "0.0.9"
+ version: "4.0.1"
archive:
dependency: transitive
description:
name: archive
- sha256: ca12e6c9ac022f33fd89128e7007fb5e97ab6e814d4fa05dd8d4f2db1e3c69cb
+ sha256: "22600aa1e926be775fa5fe7e6894e7fb3df9efda8891c73f70fb3262399a432d"
url: "https://pub.dev"
source: hosted
- version: "3.4.5"
+ version: "3.4.10"
args:
dependency: "direct main"
description:
name: args
- sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596
+ sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a"
url: "https://pub.dev"
source: hosted
- version: "2.4.2"
+ version: "2.5.0"
async:
dependency: "direct main"
description:
@@ -133,18 +69,18 @@ packages:
dependency: "direct main"
description:
name: audio_service
- sha256: a4d989f1225ea9621898d60f23236dcbfc04876fa316086c23c5c4af075dbac4
+ sha256: "4547c312a94f9cb2c48b60823fb190767cbd63454a83c73049384d5d3cba4650"
url: "https://pub.dev"
source: hosted
- version: "0.18.12"
+ version: "0.18.13"
audio_service_mpris:
dependency: "direct main"
description:
name: audio_service_mpris
- sha256: "31be5de2db0c71b217157afce1974ac6d0ad329bd91deb1f19ad094d29340d8e"
+ sha256: a8d1583f9143d17b2facc994a99bd1ea257cec43adcb8d7349458555c62b570f
url: "https://pub.dev"
source: hosted
- version: "0.1.0"
+ version: "0.1.3"
audio_service_platform_interface:
dependency: transitive
description:
@@ -157,18 +93,18 @@ packages:
dependency: transitive
description:
name: audio_service_web
- sha256: "523e64ddc914c714d53eec2da85bba1074f08cf26c786d4efb322de510815ea7"
+ sha256: "9d7d5ae5f98a5727f2580fad73062f2484f400eef6cef42919413268e62a363e"
url: "https://pub.dev"
source: hosted
- version: "0.1.1"
+ version: "0.1.2"
audio_session:
dependency: "direct main"
description:
name: audio_session
- sha256: "6fdf255ed3af86535c96452c33ecff1245990bb25a605bfb1958661ccc3d467f"
+ sha256: a49af9981eec5d7cd73b37bacb6ee73f8143a6a9f9bd5b6021e6c346b9b6cf4e
url: "https://pub.dev"
source: hosted
- version: "0.1.18"
+ version: "0.1.19"
auto_size_text:
dependency: "direct main"
description:
@@ -261,18 +197,18 @@ packages:
dependency: transitive
description:
name: build_daemon
- sha256: "5f02d73eb2ba16483e693f80bee4f088563a820e47d1027d4cdfe62b5bb43e65"
+ sha256: "0343061a33da9c5810b2d6cee51945127d8f4c060b7fbdd9d54917f0a3feaaa1"
url: "https://pub.dev"
source: hosted
- version: "4.0.0"
+ version: "4.0.1"
build_resolvers:
dependency: transitive
description:
name: build_resolvers
- sha256: d912852cce27c9e80a93603db721c267716894462e7033165178b91138587972
+ sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a"
url: "https://pub.dev"
source: hosted
- version: "2.3.2"
+ version: "2.4.2"
build_runner:
dependency: "direct dev"
description:
@@ -285,10 +221,10 @@ packages:
dependency: transitive
description:
name: build_runner_core
- sha256: "6d6ee4276b1c5f34f21fdf39425202712d2be82019983d52f351c94aafbc2c41"
+ sha256: "4ae8ffe5ac758da294ecf1802f2aff01558d8b1b00616aa7538ea9a8a5d50799"
url: "https://pub.dev"
source: hosted
- version: "7.2.10"
+ version: "7.3.0"
built_collection:
dependency: transitive
description:
@@ -301,18 +237,18 @@ packages:
dependency: transitive
description:
name: built_value
- sha256: ff627b645b28fb8bdb69e645f910c2458fd6b65f6585c3a53e0626024897dedf
+ sha256: c7913a9737ee4007efedaffc968c049fd0f3d0e49109e778edc10de9426005cb
url: "https://pub.dev"
source: hosted
- version: "8.6.2"
+ version: "8.9.2"
buttons_tabbar:
dependency: "direct main"
description:
name: buttons_tabbar
- sha256: "781128180f3e76cf93c093183f10395c664983dbee20bc4da2025be70085c2da"
+ sha256: "3f0969c26574ef15c0c9ff1dee42c3c4b0d3563d2c8607804372490fb8b76896"
url: "https://pub.dev"
source: hosted
- version: "1.3.7+1"
+ version: "1.3.8"
cached_network_image:
dependency: "direct main"
description:
@@ -341,10 +277,10 @@ packages:
dependency: "direct main"
description:
name: catcher_2
- sha256: "73e251057b1b59442d58b5109d26401cfed850df21da44b028338d4f85f69105"
+ sha256: "3c8f6cedc8c5eab61192830096d4f303900a5d0bddbf96a07ff9f7a8d5ff8fcd"
url: "https://pub.dev"
source: hosted
- version: "1.0.0"
+ version: "1.2.4"
change_case:
dependency: transitive
description:
@@ -381,10 +317,10 @@ packages:
dependency: transitive
description:
name: cli_util
- sha256: b8db3080e59b2503ca9e7922c3df2072cf13992354d5e944074ffa836fba43b7
+ sha256: c05b7406fdabc7a49a3929d4af76bcaccbbffcbcdcf185b082e1ae07da323d19
url: "https://pub.dev"
source: hosted
- version: "0.4.0"
+ version: "0.4.1"
clock:
dependency: transitive
description:
@@ -397,10 +333,10 @@ packages:
dependency: transitive
description:
name: code_builder
- sha256: "315a598c7fbe77f22de1c9da7cfd6fd21816312f16ffa124453b4fc679e540f1"
+ sha256: f692079e25e7869c14132d39f223f8eec9830eb76131925143b2129c4bb01b37
url: "https://pub.dev"
source: hosted
- version: "4.6.0"
+ version: "4.10.0"
collection:
dependency: "direct main"
description:
@@ -429,10 +365,10 @@ packages:
dependency: transitive
description:
name: cross_file
- sha256: fd832b5384d0d6da4f6df60b854d33accaaeb63aa9e10e736a87381f08dee2cb
+ sha256: "55d7b444feb71301ef6b8838dbc1ae02e63dd48c8773f3810ff53bb1e2945b32"
url: "https://pub.dev"
source: hosted
- version: "0.3.3+5"
+ version: "0.3.4+1"
crypto:
dependency: "direct main"
description:
@@ -449,14 +385,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.0"
- cupertino_icons:
- dependency: "direct main"
- description:
- name: cupertino_icons
- sha256: d57953e10f9f8327ce64a508a355f0b1ec902193f66288e8cb5070e7c47eeb2d
- url: "https://pub.dev"
- source: hosted
- version: "1.0.6"
curved_navigation_bar:
dependency: "direct main"
description:
@@ -469,26 +397,26 @@ packages:
dependency: "direct dev"
description:
name: custom_lint
- sha256: "22bd87a362f433ba6aae127a7bac2838645270737f3721b180916d7c5946cb5d"
+ sha256: "7c0aec12df22f9082146c354692056677f1e70bc43471644d1fdb36c6fdda799"
url: "https://pub.dev"
source: hosted
- version: "0.5.11"
+ version: "0.6.4"
custom_lint_builder:
dependency: transitive
description:
name: custom_lint_builder
- sha256: "0d48e002438950f9582e574ef806b2bea5719d8d14c0f9f754fbad729bcf3b19"
+ sha256: d7dc41e709dde223806660268678be7993559e523eb3164e2a1425fd6f7615a9
url: "https://pub.dev"
source: hosted
- version: "0.5.14"
+ version: "0.6.4"
custom_lint_core:
dependency: transitive
description:
name: custom_lint_core
- sha256: "2952837953022de610dacb464f045594854ced6506ac7f76af28d4a6490e189b"
+ sha256: a85e8f78f4c52f6c63cdaf8c872eb573db0231dcdf3c3a5906d493c1f8bc20e6
url: "https://pub.dev"
source: hosted
- version: "0.5.14"
+ version: "0.6.3"
dart_des:
dependency: transitive
description:
@@ -506,14 +434,22 @@ packages:
url: "https://github.com/Tommypop2/dart_discord_rpc.git"
source: git
version: "0.0.3"
+ dart_mappable:
+ dependency: transitive
+ description:
+ name: dart_mappable
+ sha256: "47269caf2060533c29b823ff7fa9706502355ffcb61e7f2a374e3a0fb2f2c3f0"
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.2.2"
dart_style:
dependency: transitive
description:
name: dart_style
- sha256: "1efa911ca7086affd35f463ca2fc1799584fb6aa89883cf0af8e3664d6a02d55"
+ sha256: "99e066ce75c89d6b29903d788a7bb9369cf754f7b24bf70bf4b6d6d6b26853b9"
url: "https://pub.dev"
source: hosted
- version: "2.3.2"
+ version: "2.3.6"
dartx:
dependency: transitive
description:
@@ -542,10 +478,10 @@ packages:
dependency: "direct main"
description:
name: device_info_plus
- sha256: "77f757b789ff68e4eaf9c56d1752309bd9f7ad557cb105b938a7f8eb89e59110"
+ sha256: eead12d1a1ed83d8283ab4c2f3fca23ac4082f29f25f29dff0f758f57d06ec91
url: "https://pub.dev"
source: hosted
- version: "9.1.2"
+ version: "10.1.0"
device_info_plus_platform_interface:
dependency: transitive
description:
@@ -566,18 +502,18 @@ packages:
dependency: "direct main"
description:
name: dio
- sha256: "49af28382aefc53562459104f64d16b9dfd1e8ef68c862d5af436cc8356ce5a8"
+ sha256: "11e40df547d418cc0c4900a9318b26304e665da6fa4755399a9ff9efd09034b5"
url: "https://pub.dev"
source: hosted
- version: "5.4.1"
+ version: "5.4.3+1"
disable_battery_optimization:
dependency: "direct main"
description:
name: disable_battery_optimization
- sha256: b3441975ab2a3ab0c19ed78e909a88d245ce689d43d17f9b23582b1ed41c047b
+ sha256: "6b2ba802f984af141faf1b6b5fb956d5ef01f9cd555597c35b9cc335a03185ba"
url: "https://pub.dev"
source: hosted
- version: "1.1.0+1"
+ version: "1.1.1"
dots_indicator:
dependency: transitive
description:
@@ -607,18 +543,26 @@ packages:
dependency: "direct main"
description:
name: envied
- sha256: "60d3f5606c7b35bc6ef493e650d916b34351d8af2e58b7ac45881ba59dfcf039"
+ sha256: bbff9c76120e4dc5e2e36a46690cf0a26feb65e7765633f4e8d916bcd173a450
url: "https://pub.dev"
source: hosted
- version: "0.3.0+3"
+ version: "0.5.4+1"
envied_generator:
dependency: "direct dev"
description:
name: envied_generator
- sha256: dfdbe5dc52863e54c036a4c4042afbdf1bd528cb4c1e638ecba26228ba72e9e5
+ sha256: "517b70de08d13dcd40e97b4e5347e216a0b1c75c99e704f3c85c0474a392d14a"
url: "https://pub.dev"
source: hosted
- version: "0.3.0+3"
+ version: "0.5.4+1"
+ equatable:
+ dependency: transitive
+ description:
+ name: equatable
+ sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.0.5"
fake_async:
dependency: transitive
description:
@@ -631,10 +575,10 @@ packages:
dependency: transitive
description:
name: ffi
- sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878"
+ sha256: "493f37e7df1804778ff3a53bd691d8692ddf69702cf4c1c1096a2e41b4779e21"
url: "https://pub.dev"
source: hosted
- version: "2.1.0"
+ version: "2.1.2"
file:
dependency: transitive
description:
@@ -647,34 +591,34 @@ packages:
dependency: "direct main"
description:
name: file_picker
- sha256: "4e42aacde3b993c5947467ab640882c56947d9d27342a5b6f2895b23956954a6"
+ sha256: d1d0ac3966b36dc3e66eeefb40280c17feb87fa2099c6e22e6a1fc959327bd03
url: "https://pub.dev"
source: hosted
- version: "6.1.1"
+ version: "8.0.0+1"
file_selector:
dependency: "direct main"
description:
name: file_selector
- sha256: "84eaf3e034d647859167d1f01cfe7b6352488f34c1b4932635012b202014c25b"
+ sha256: "5019692b593455127794d5718304ff1ae15447dea286cdda9f0db2a796a1b828"
url: "https://pub.dev"
source: hosted
- version: "1.0.1"
+ version: "1.0.3"
file_selector_android:
dependency: transitive
description:
name: file_selector_android
- sha256: d41e165d6f798ca941d536e5dc93494d50e78c571c28ad60cfe0b0fefeb9f1e7
+ sha256: "1cd66575f063b689e041aec836905ba7be18d76c9f0634d0d75daec825f67095"
url: "https://pub.dev"
source: hosted
- version: "0.5.0+3"
+ version: "0.5.0+7"
file_selector_ios:
dependency: transitive
description:
name: file_selector_ios
- sha256: b3fbdda64aa2e335df6e111f6b0f1bb968402ed81d2dd1fa4274267999aa32c2
+ sha256: "0a1196a9c5795858aa315332da2fb5c4bcfdcb312d8a4e27651f765b87904431"
url: "https://pub.dev"
source: hosted
- version: "0.5.1+6"
+ version: "0.5.1+9"
file_selector_linux:
dependency: transitive
description:
@@ -687,26 +631,26 @@ packages:
dependency: transitive
description:
name: file_selector_macos
- sha256: "182c3f8350cee659f7b115e956047ee3dc672a96665883a545e81581b9a82c72"
+ sha256: b15c3da8bd4908b9918111fa486903f5808e388b8d1c559949f584725a6594d6
url: "https://pub.dev"
source: hosted
- version: "0.9.3+2"
+ version: "0.9.3+3"
file_selector_platform_interface:
dependency: transitive
description:
name: file_selector_platform_interface
- sha256: "0aa47a725c346825a2bd396343ce63ac00bda6eff2fbc43eabe99737dede8262"
+ sha256: a3994c26f10378a039faa11de174d7b78eb8f79e4dd0af2a451410c1a5c3f66b
url: "https://pub.dev"
source: hosted
- version: "2.6.1"
+ version: "2.6.2"
file_selector_web:
dependency: transitive
description:
name: file_selector_web
- sha256: dc6622c4d66cb1bee623ddcc029036603c6cc45c85e4a775bb06008d61c809c1
+ sha256: "619e431b224711a3869e30dbd7d516f5f5a4f04b265013a50912f39e1abc88c8"
url: "https://pub.dev"
source: hosted
- version: "0.9.2+1"
+ version: "0.9.4+1"
file_selector_windows:
dependency: transitive
description:
@@ -727,31 +671,15 @@ packages:
dependency: "direct main"
description:
name: fluentui_system_icons
- sha256: "7637cab80bd8d1ba762144cd85df79a7318c12ed5a66d166a9e4acbf24a4c412"
+ sha256: "1c860f10a0e74c5788ff8a650ae6074d9a544463ae269714f1044b32df52b978"
url: "https://pub.dev"
source: hosted
- version: "1.1.214"
+ version: "1.1.234"
flutter:
dependency: "direct main"
description: flutter
source: sdk
version: "0.0.0"
- flutter_app_builder:
- dependency: transitive
- description:
- name: flutter_app_builder
- sha256: "9e5527919f62424f0fafaa3e8dfda8469caf63e465862e9866a0d60a37c00fcf"
- url: "https://pub.dev"
- source: hosted
- version: "0.0.9"
- flutter_app_packager:
- dependency: transitive
- description:
- name: flutter_app_packager
- sha256: b5bfb7113b49710c004c5f1ab6f08ac121418540d49e14825dd75e99810fa695
- url: "https://pub.dev"
- source: hosted
- version: "0.0.9"
flutter_broadcasts:
dependency: "direct main"
description:
@@ -768,15 +696,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.3.1"
- flutter_desktop_tools:
- dependency: "direct main"
- description:
- path: "."
- ref: "1f0bec3283626dcbd8ee2f54e238d096d8dea50e"
- resolved-ref: "1f0bec3283626dcbd8ee2f54e238d096d8dea50e"
- url: "https://github.com/KRTirtho/flutter_desktop_tools.git"
- source: git
- version: "0.0.1"
flutter_displaymode:
dependency: "direct main"
description:
@@ -785,14 +704,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.6.0"
- flutter_distributor:
- dependency: "direct dev"
- description:
- name: flutter_distributor
- sha256: "50d56df265e97396427ec42cc02374b72d08c71b3442d662b97fc089bd1705ea"
- url: "https://pub.dev"
- source: hosted
- version: "0.0.2"
flutter_driver:
dependency: transitive
description: flutter
@@ -890,10 +801,10 @@ packages:
dependency: transitive
description:
name: flutter_keyboard_visibility
- sha256: "4983655c26ab5b959252ee204c2fffa4afeb4413cd030455194ec0caa3b8e7cb"
+ sha256: "98664be7be0e3ffca00de50f7f6a287ab62c763fc8c762e0a21584584a3ff4f8"
url: "https://pub.dev"
source: hosted
- version: "5.4.1"
+ version: "6.0.0"
flutter_keyboard_visibility_linux:
dependency: transitive
description:
@@ -946,10 +857,10 @@ packages:
dependency: "direct dev"
description:
name: flutter_lints
- sha256: e2a421b7e59244faef694ba7b30562e489c2b489866e505074eb005cd7060db7
+ sha256: "9e8c3858111da373efc5aa341de011d9bd23e2c5c5e0c62bccf32438e192d7b1"
url: "https://pub.dev"
source: hosted
- version: "3.0.1"
+ version: "3.0.2"
flutter_localizations:
dependency: "direct main"
description: flutter
@@ -959,42 +870,42 @@ packages:
dependency: transitive
description:
name: flutter_mailer
- sha256: a935e9caa842877e8ed56109afb75b86e6488edbcd4696a5ac02b327a48fcd8a
+ sha256: "4fffaa35e911ff5ec2e5a4ebbca62c372e99a154eb3bb2c0bf79f09adf6ecf4c"
url: "https://pub.dev"
source: hosted
- version: "2.1.1"
+ version: "2.1.2"
flutter_native_splash:
dependency: "direct main"
description:
name: flutter_native_splash
- sha256: "558f10070f03ee71f850a78f7136ab239a67636a294a44a06b6b7345178edb1e"
+ sha256: edf39bcf4d74aca1eb2c1e43c3e445fd9f494013df7f0da752fefe72020eedc0
url: "https://pub.dev"
source: hosted
- version: "2.3.10"
+ version: "2.4.0"
flutter_plugin_android_lifecycle:
dependency: transitive
description:
name: flutter_plugin_android_lifecycle
- sha256: f185ac890306b5779ecbd611f52502d8d4d63d27703ef73161ca0407e815f02c
+ sha256: "8cf40eebf5dec866a6d1956ad7b4f7016e6c0cc69847ab946833b7d43743809f"
url: "https://pub.dev"
source: hosted
- version: "2.0.16"
+ version: "2.0.19"
flutter_riverpod:
dependency: "direct main"
description:
name: flutter_riverpod
- sha256: "4bce556b7ecbfea26109638d5237684538d4abc509d253e6c5c4c5733b360098"
+ sha256: "0f1974eff5bbe774bf1d870e406fc6f29e3d6f1c46bd9c58e7172ff68a785d7d"
url: "https://pub.dev"
source: hosted
- version: "2.4.10"
+ version: "2.5.1"
flutter_rust_bridge:
dependency: transitive
description:
name: flutter_rust_bridge
- sha256: e12415c3bce49bcbc3fed383f0ea41ad7d828f6cf0eccba0588ffa5a812fe522
+ sha256: "02720226035257ad0b571c1256f43df3e1556a499f6bcb004849a0faaa0e87f0"
url: "https://pub.dev"
source: hosted
- version: "1.82.1"
+ version: "1.82.6"
flutter_secure_storage:
dependency: "direct main"
description:
@@ -1047,10 +958,10 @@ packages:
dependency: "direct main"
description:
name: flutter_sharing_intent
- sha256: "6eb896e6523b735e8230eeb206fd3b9f220f11ce879c2400a90b443147036ff9"
+ sha256: "785ffc391822641457f930eb477c91c2f598a888f50b8fbb40d481ee01c7e719"
url: "https://pub.dev"
source: hosted
- version: "1.1.0"
+ version: "1.1.1"
flutter_svg:
dependency: "direct main"
description:
@@ -1073,10 +984,10 @@ packages:
dependency: transitive
description:
name: fluttertoast
- sha256: "474f7d506230897a3cd28c965ec21c5328ae5605fc9c400cd330e9e9d6ac175c"
+ sha256: "81b68579e23fcbcada2db3d50302813d2371664afe6165bc78148050ab94bf66"
url: "https://pub.dev"
source: hosted
- version: "8.2.2"
+ version: "8.2.5"
form_validator:
dependency: "direct main"
description:
@@ -1089,10 +1000,10 @@ packages:
dependency: "direct dev"
description:
name: freezed
- sha256: "6c5031daae12c7072b3a87eff98983076434b4889ef2a44384d0cae3f82372ba"
+ sha256: a434911f643466d78462625df76fd9eb13e57348ff43fe1f77bbe909522c67a1
url: "https://pub.dev"
source: hosted
- version: "2.4.6"
+ version: "2.5.2"
freezed_annotation:
dependency: "direct main"
description:
@@ -1105,10 +1016,10 @@ packages:
dependency: transitive
description:
name: frontend_server_client
- sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612"
+ sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694
url: "https://pub.dev"
source: hosted
- version: "3.2.0"
+ version: "4.0.0"
fuchsia_remote_debug_protocol:
dependency: transitive
description: flutter
@@ -1150,10 +1061,10 @@ packages:
dependency: "direct main"
description:
name: google_fonts
- sha256: f0b8d115a13ecf827013ec9fc883390ccc0e87a96ed5347a3114cac177ef18e8
+ sha256: b1ac0fe2832c9cc95e5e88b57d627c5e68c223b9657f4b96e1487aa9098c7b82
url: "https://pub.dev"
source: hosted
- version: "6.1.0"
+ version: "6.2.1"
graphs:
dependency: transitive
description:
@@ -1206,10 +1117,10 @@ packages:
dependency: "direct main"
description:
name: hooks_riverpod
- sha256: "758b07eba336e3cbacbd81dba481f2228a14102083fdde07045e8514e8054c49"
+ sha256: "45b2030a18bcd6dbd680c2c91bc3b33e3fe7c323e3acb5ecec93a613e2fbaa8a"
url: "https://pub.dev"
source: hosted
- version: "2.4.10"
+ version: "2.5.1"
hotreloader:
dependency: transitive
description:
@@ -1270,42 +1181,42 @@ packages:
dependency: transitive
description:
name: image
- sha256: "028f61960d56f26414eb616b48b04eb37d700cbe477b7fb09bf1d7ce57fd9271"
+ sha256: "4c68bfd5ae83e700b5204c1e74451e7bf3cf750e6843c6e158289cf56bda018e"
url: "https://pub.dev"
source: hosted
- version: "4.1.3"
+ version: "4.1.7"
image_picker:
dependency: "direct main"
description:
name: image_picker
- sha256: "7d7f2768df2a8b0a3cefa5ef4f84636121987d403130e70b17ef7e2cf650ba84"
+ sha256: fe9ee64ccb8d599a5dfb0e21cc6652232c610bcf667af4e79b9eb175cc30a7a5
url: "https://pub.dev"
source: hosted
- version: "1.0.4"
+ version: "1.1.0"
image_picker_android:
dependency: transitive
description:
name: image_picker_android
- sha256: "47da2161c2e9f8f8a9cbbd89d466d174333fbdd769aeed848912e0b16d9cb369"
+ sha256: "8e75431a62b7feb4fd55cb4a5c6f0ac4564460ec5dc09f9c4a0d50a5ce7c4cb9"
url: "https://pub.dev"
source: hosted
- version: "0.8.8"
+ version: "0.8.10"
image_picker_for_web:
dependency: transitive
description:
name: image_picker_for_web
- sha256: "50bc9ae6a77eea3a8b11af5eb6c661eeb858fdd2f734c2a4fd17086922347ef7"
+ sha256: "5d6eb13048cd47b60dbf1a5495424dea226c5faf3950e20bf8120a58efb5b5f3"
url: "https://pub.dev"
source: hosted
- version: "3.0.1"
+ version: "3.0.4"
image_picker_ios:
dependency: transitive
description:
name: image_picker_ios
- sha256: c5538cacefacac733c724be7484377923b476216ad1ead35a0d2eadcdc0fc497
+ sha256: f4a6f62be96d6fd268f32a6bf8ef444cd8e3fff64d16923c6e6fe55e0c84a761
url: "https://pub.dev"
source: hosted
- version: "0.8.8+2"
+ version: "0.8.10"
image_picker_linux:
dependency: transitive
description:
@@ -1326,10 +1237,10 @@ packages:
dependency: transitive
description:
name: image_picker_platform_interface
- sha256: ed9b00e63977c93b0d2d2b343685bed9c324534ba5abafbb3dfbd6a780b1b514
+ sha256: "9ec26d410ff46f483c5519c29c02ef0e02e13a543f882b152d4bfd2f06802f80"
url: "https://pub.dev"
source: hosted
- version: "2.9.1"
+ version: "2.10.0"
image_picker_windows:
dependency: transitive
description:
@@ -1355,10 +1266,10 @@ packages:
dependency: "direct main"
description:
name: introduction_screen
- sha256: ef5a5479a8e06a84b9a7eff16c698b9b82f70cd1b6203b264bc3686f9bfb77e2
+ sha256: "325f26e86fa3c3e86e6ab2bbc1fda860c9e6eae5ff29166fc2a3cab8f710d5b5"
url: "https://pub.dev"
source: hosted
- version: "3.1.11"
+ version: "3.1.14"
io:
dependency: transitive
description:
@@ -1432,21 +1343,21 @@ packages:
source: hosted
version: "3.0.0"
local_notifier:
- dependency: transitive
+ dependency: "direct main"
description:
name: local_notifier
- sha256: cc855aa6362c8840e3d3b35b1c3b058a3a8becdb2b03d5a9aa3f3a1e861f0a03
+ sha256: f6cfc933c6fbc961f4e52b5c880f68e41b2d3cd29aad557cc654fd211093a025
url: "https://pub.dev"
source: hosted
- version: "0.1.5"
+ version: "0.1.6"
logger:
dependency: "direct main"
description:
name: logger
- sha256: ba3bc83117b2b49bdd723c0ea7848e8285a0fbc597ba09203b20d329d020c24a
+ sha256: "8c94b8c219e7e50194efc8771cd0e9f10807d8d3e219af473d89b06cc2ee4e04"
url: "https://pub.dev"
source: hosted
- version: "2.0.2"
+ version: "2.2.0"
logging:
dependency: transitive
description:
@@ -1467,10 +1378,10 @@ packages:
dependency: transitive
description:
name: mailer
- sha256: "57f6dd1496699999a7bfd0aa6be0645384f477f4823e16d4321c40a434346382"
+ sha256: d25d89555c1031abacb448f07b801d7c01b4c21d4558e944b12b64394c84a3cb
url: "https://pub.dev"
source: hosted
- version: "6.0.1"
+ version: "6.1.0"
matcher:
dependency: transitive
description:
@@ -1491,26 +1402,26 @@ packages:
dependency: "direct main"
description:
name: media_kit
- sha256: "92c7f59e075d74471b31e703f81ccc1d7102739ebcce945b30a6417fa2f751d5"
+ sha256: "3289062540e3b8b9746e5c50d95bd78a9289826b7227e253dff806d002b9e67a"
url: "https://pub.dev"
source: hosted
- version: "1.1.7"
+ version: "1.1.10+1"
media_kit_libs_android_audio:
dependency: transitive
description:
name: media_kit_libs_android_audio
- sha256: "1d9ba8814e58a12ae69014884abf96893d38e444abfb806ff38896dfe089dd15"
+ sha256: "3d2df5c09d3f3ff7c55b53bf955e46712f76483e77562a5a017439a3ea85ce88"
url: "https://pub.dev"
source: hosted
- version: "1.3.5"
+ version: "1.3.6"
media_kit_libs_audio:
dependency: "direct main"
description:
name: media_kit_libs_audio
- sha256: "9ccf9019edc220b8d0bfa1f53a91aa2cf2506ac860b4d5774c9d6bbdd49796ca"
+ sha256: f3f91df69848005363b3ae0ef7971a90edbd80a9365195684ef26c9a6ac8833f
url: "https://pub.dev"
source: hosted
- version: "1.0.3"
+ version: "1.0.4"
media_kit_libs_ios_audio:
dependency: transitive
description:
@@ -1551,6 +1462,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.8"
+ menu_base:
+ dependency: transitive
+ description:
+ name: menu_base
+ sha256: "820368014a171bd1241030278e6c2617354f492f5c703d7b7d4570a6b8b84405"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.1.1"
meta:
dependency: transitive
description:
@@ -1571,10 +1490,10 @@ packages:
dependency: "direct main"
description:
name: mime
- sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e
+ sha256: "2e123074287cc9fd6c09de8336dae606d1ddb88d9ac47358826db698c176a1f2"
url: "https://pub.dev"
source: hosted
- version: "1.0.4"
+ version: "1.0.5"
nested:
dependency: transitive
description:
@@ -1611,10 +1530,10 @@ packages:
dependency: "direct main"
description:
name: package_info_plus
- sha256: "6ff267fcd9d48cb61c8df74a82680e8b82e940231bb5f68356672fde0397334a"
+ sha256: cb44f49b6e690fa766f023d5b22cac6b9affe741dd792b6ac7ad4fabe0d7b097
url: "https://pub.dev"
source: hosted
- version: "4.1.0"
+ version: "6.0.0"
package_info_plus_platform_interface:
dependency: transitive
description:
@@ -1659,26 +1578,26 @@ packages:
dependency: "direct main"
description:
name: path_provider
- sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa
+ sha256: c9e7d3a4cd1410877472158bee69963a4579f78b68c65a2b7d40d1a7a88bb161
url: "https://pub.dev"
source: hosted
- version: "2.1.1"
+ version: "2.1.3"
path_provider_android:
dependency: transitive
description:
name: path_provider_android
- sha256: "6b8b19bd80da4f11ce91b2d1fb931f3006911477cec227cce23d3253d80df3f1"
+ sha256: a248d8146ee5983446bf03ed5ea8f6533129a12b11f12057ad1b4a67a2b3b41d
url: "https://pub.dev"
source: hosted
- version: "2.2.0"
+ version: "2.2.4"
path_provider_foundation:
dependency: transitive
description:
name: path_provider_foundation
- sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d"
+ sha256: "5a7999be66e000916500be4f15a3633ebceb8302719b47b9cc49ce924125350f"
url: "https://pub.dev"
source: hosted
- version: "2.3.1"
+ version: "2.3.2"
path_provider_linux:
dependency: transitive
description:
@@ -1691,10 +1610,10 @@ packages:
dependency: transitive
description:
name: path_provider_platform_interface
- sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c"
+ sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334"
url: "https://pub.dev"
source: hosted
- version: "2.1.1"
+ version: "2.1.2"
path_provider_windows:
dependency: transitive
description:
@@ -1707,42 +1626,50 @@ packages:
dependency: "direct main"
description:
name: permission_handler
- sha256: "284a66179cabdf942f838543e10413246f06424d960c92ba95c84439154fcac8"
+ sha256: "18bf33f7fefbd812f37e72091a15575e72d5318854877e0e4035a24ac1113ecb"
url: "https://pub.dev"
source: hosted
- version: "11.0.1"
+ version: "11.3.1"
permission_handler_android:
dependency: transitive
description:
name: permission_handler_android
- sha256: ace7d15a3d1a4a0b91c041d01e5405df221edb9de9116525efc773c74e6fc790
+ sha256: "1acac6bae58144b442f11e66621c062aead9c99841093c38f5bcdcc24c1c3474"
url: "https://pub.dev"
source: hosted
- version: "11.0.5"
+ version: "12.0.5"
permission_handler_apple:
dependency: transitive
description:
name: permission_handler_apple
- sha256: "99e220bce3f8877c78e4ace901082fb29fa1b4ebde529ad0932d8d664b34f3f5"
+ sha256: e9ad66020b89ff1b63908f247c2c6f931c6e62699b756ef8b3c4569350cd8662
url: "https://pub.dev"
source: hosted
- version: "9.1.4"
+ version: "9.4.4"
+ permission_handler_html:
+ dependency: transitive
+ description:
+ name: permission_handler_html
+ sha256: "54bf176b90f6eddd4ece307e2c06cf977fb3973719c35a93b85cc7093eb6070d"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.1.1"
permission_handler_platform_interface:
dependency: transitive
description:
name: permission_handler_platform_interface
- sha256: f2343e9fa9c22ae4fd92d4732755bfe452214e7189afcc097380950cf567b4b2
+ sha256: "48d4fcf201a1dad93ee869ab0d4101d084f49136ec82a8a06ed9cfeacab9fd20"
url: "https://pub.dev"
source: hosted
- version: "3.11.5"
+ version: "4.2.1"
permission_handler_windows:
dependency: transitive
description:
name: permission_handler_windows
- sha256: cc074aace208760f1eee6aa4fae766b45d947df85bc831cde77009cdb4720098
+ sha256: "1a790728016f79a41216d88672dbc5df30e686e811ad4e698bfc51f76ad91f1e"
url: "https://pub.dev"
source: hosted
- version: "0.1.3"
+ version: "0.2.1"
petitparser:
dependency: transitive
description:
@@ -1754,11 +1681,10 @@ packages:
piped_client:
dependency: "direct main"
description:
- path: "."
- ref: HEAD
- resolved-ref: "64631732eefe3d93889756dc2e4ff5c8523ed763"
- url: "https://github.com/KRTirtho/piped_client.git"
- source: git
+ name: piped_client
+ sha256: "87b04b2ebf4e008cfbb0ac85e9920ab3741f5aa697be2dd44919658a3297a4bc"
+ url: "https://pub.dev"
+ source: hosted
version: "0.1.1"
platform:
dependency: transitive
@@ -1772,18 +1698,18 @@ packages:
dependency: transitive
description:
name: plugin_platform_interface
- sha256: da3fdfeccc4d4ff2da8f8c556704c08f912542c5fb3cf2233ed75372384a034d
+ sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
url: "https://pub.dev"
source: hosted
- version: "2.1.6"
+ version: "2.1.8"
pointycastle:
dependency: transitive
description:
name: pointycastle
- sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c"
+ sha256: "70fe966348fe08c34bf929582f1d8247d9d9408130723206472b4687227e4333"
url: "https://pub.dev"
source: hosted
- version: "3.7.3"
+ version: "3.8.0"
pool:
dependency: transitive
description:
@@ -1812,18 +1738,18 @@ packages:
dependency: transitive
description:
name: provider
- sha256: cdbe7530b12ecd9eb455bdaa2fcb8d4dad22e80b8afb4798b41479d5ce26847f
+ sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c
url: "https://pub.dev"
source: hosted
- version: "6.0.5"
+ version: "6.1.2"
pub_api_client:
dependency: "direct main"
description:
name: pub_api_client
- sha256: d456816ef5142906a22dc56e37be6bef6cb0276f0a26c11d1f7d277868202e71
+ sha256: cc3d2c93df3823553de6a3e7d3ac09a3f43f8c271af4f43c2795266090ac9625
url: "https://pub.dev"
source: hosted
- version: "2.6.0"
+ version: "2.7.0"
pub_semver:
dependency: transitive
description:
@@ -1852,10 +1778,10 @@ packages:
dependency: transitive
description:
name: puppeteer
- sha256: eedeaae6ec5d2e54f9ae22ab4d6b3dda2e8791c356cc783046d06c287ffe11d8
+ sha256: "6833edca01b1e9dcdd9a6e41bad84b706dfba4366d095c4edff64b00c02ac472"
url: "https://pub.dev"
source: hosted
- version: "3.6.0"
+ version: "3.8.0"
quiver:
dependency: transitive
description:
@@ -1864,30 +1790,38 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.2.1"
+ recase:
+ dependency: transitive
+ description:
+ name: recase
+ sha256: e4eb4ec2dcdee52dcf99cb4ceabaffc631d7424ee55e56f280bc039737f89213
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.1.0"
riverpod:
dependency: transitive
description:
name: riverpod
- sha256: "548e2192eb7aeb826eb89387f814edb76594f3363e2c0bb99dd733d795ba3589"
+ sha256: f21b32ffd26a36555e501b04f4a5dca43ed59e16343f1a30c13632b2351dfa4d
url: "https://pub.dev"
source: hosted
- version: "2.5.0"
+ version: "2.5.1"
riverpod_analyzer_utils:
dependency: transitive
description:
name: riverpod_analyzer_utils
- sha256: d72d7096964baf288b55619fe48100001fc4564ab7923ed0a7f5c7650e03c0d6
+ sha256: "8b71f03fc47ae27d13769496a1746332df4cec43918aeba9aff1e232783a780f"
url: "https://pub.dev"
source: hosted
- version: "0.3.4"
+ version: "0.5.1"
riverpod_lint:
dependency: "direct dev"
description:
name: riverpod_lint
- sha256: "70198738c3047ae4f6517ef1a2011a8514a980a52576c7f629a3a08810319a02"
+ sha256: "3c67c14ccd16f0c9d53e35ef70d06cd9d072e2fb14557326886bbde903b230a5"
url: "https://pub.dev"
source: hosted
- version: "2.1.1"
+ version: "2.3.10"
rxdart:
dependency: transitive
description:
@@ -1933,34 +1867,34 @@ packages:
dependency: transitive
description:
name: sentry
- sha256: "39c23342fc96105da449914f7774139a17a0ca8a4e70d9ad5200171f7e47d6ba"
+ sha256: "19a267774906ca3a3c4677fc7e9582ea9da79ae9a28f84bbe4885dac2c269b70"
url: "https://pub.dev"
source: hosted
- version: "7.9.0"
+ version: "7.20.0"
shared_preferences:
dependency: "direct main"
description:
name: shared_preferences
- sha256: "81429e4481e1ccfb51ede496e916348668fd0921627779233bd24cc3ff6abd02"
+ sha256: d3bbe5553a986e83980916ded2f0b435ef2e1893dfaa29d5a7a790d0eca12180
url: "https://pub.dev"
source: hosted
- version: "2.2.2"
+ version: "2.2.3"
shared_preferences_android:
dependency: transitive
description:
name: shared_preferences_android
- sha256: "8568a389334b6e83415b6aae55378e158fbc2314e074983362d20c562780fb06"
+ sha256: "1ee8bf911094a1b592de7ab29add6f826a7331fb854273d55918693d5364a1f2"
url: "https://pub.dev"
source: hosted
- version: "2.2.1"
+ version: "2.2.2"
shared_preferences_foundation:
dependency: transitive
description:
name: shared_preferences_foundation
- sha256: "7bf53a9f2d007329ee6f3df7268fd498f8373602f943c975598bbb34649b62a7"
+ sha256: "7708d83064f38060c7b39db12aefe449cb8cdc031d6062280087bc4cdb988f5c"
url: "https://pub.dev"
source: hosted
- version: "2.3.4"
+ version: "2.3.5"
shared_preferences_linux:
dependency: transitive
description:
@@ -1973,18 +1907,18 @@ packages:
dependency: transitive
description:
name: shared_preferences_platform_interface
- sha256: d4ec5fc9ebb2f2e056c617112aa75dcf92fc2e4faaf2ae999caa297473f75d8a
+ sha256: "22e2ecac9419b4246d7c22bfbbda589e3acf5c0351137d87dd2939d984d37c3b"
url: "https://pub.dev"
source: hosted
- version: "2.3.1"
+ version: "2.3.2"
shared_preferences_web:
dependency: transitive
description:
name: shared_preferences_web
- sha256: d762709c2bbe80626ecc819143013cc820fa49ca5e363620ee20a8b15a3e3daf
+ sha256: "9aee1089b36bd2aafe06582b7d7817fd317ef05fc30e6ba14bff247d0933042a"
url: "https://pub.dev"
source: hosted
- version: "2.2.1"
+ version: "2.3.0"
shared_preferences_windows:
dependency: transitive
description:
@@ -2025,22 +1959,30 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.4"
+ shortid:
+ dependency: transitive
+ description:
+ name: shortid
+ sha256: d0b40e3dbb50497dad107e19c54ca7de0d1a274eb9b4404991e443dadb9ebedb
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.1.2"
sidebarx:
dependency: "direct main"
description:
name: sidebarx
- sha256: "7042d64844b8e64ca5c17e70d89b49df35b54a26c015b90000da9741eab70bc0"
+ sha256: abe39d6db237fb8e25c600e8039ffab80fa7fe71acab03e9c378c31f912d2766
url: "https://pub.dev"
source: hosted
- version: "0.16.3"
+ version: "0.17.1"
simple_icons:
dependency: "direct main"
description:
name: simple_icons
- sha256: "8aa6832dc7a263a3213e40ecbf1328a392308c809d534a3b860693625890483b"
+ sha256: "30067d70a9d72923fbc80e142e17fa46085dfa970e66bc4bede3be4819d05901"
url: "https://pub.dev"
source: hosted
- version: "7.10.0"
+ version: "10.1.3"
skeleton_text:
dependency: "direct main"
description:
@@ -2053,10 +1995,10 @@ packages:
dependency: "direct main"
description:
name: skeletonizer
- sha256: ff4c36e826efd5288d7a84e7619a6e9be8185d3064cecf101a9133762f3b401b
+ sha256: "9a3ae2f4ee4349bdbed3292d04586a1315a44745d2c454684f82f0c46dbeabf9"
url: "https://pub.dev"
source: hosted
- version: "0.8.0"
+ version: "1.1.1"
sky_engine:
dependency: transitive
description: flutter
@@ -2074,18 +2016,18 @@ packages:
dependency: "direct main"
description:
name: smtc_windows
- sha256: aba2bad5ddfaf595496db04df3d9fdb54fb128fc1f39c8f024945a67455388fe
+ sha256: "799bbe0f8e4436da852c5dcc0be482c97b8ae0f504f65c6b750cd239b4835aa0"
url: "https://pub.dev"
source: hosted
- version: "0.1.1"
+ version: "0.1.2"
source_gen:
dependency: transitive
description:
name: source_gen
- sha256: fc0da689e5302edb6177fdd964efcb7f58912f43c28c2047a808f5bfff643d16
+ sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832"
url: "https://pub.dev"
source: hosted
- version: "1.4.0"
+ version: "1.5.0"
source_helper:
dependency: transitive
description:
@@ -2115,18 +2057,18 @@ packages:
dependency: transitive
description:
name: sqflite
- sha256: "591f1602816e9c31377d5f008c2d9ef7b8aca8941c3f89cc5fd9d84da0c38a9a"
+ sha256: "5ce2e1a15e822c3b4bfb5400455775e421da7098eed8adc8f26298ada7c9308c"
url: "https://pub.dev"
source: hosted
- version: "2.3.0"
+ version: "2.3.3"
sqflite_common:
dependency: transitive
description:
name: sqflite_common
- sha256: "1b92f368f44b0dee2425bb861cfa17b6f6cf3961f762ff6f941d20b33355660a"
+ sha256: "3da423ce7baf868be70e2c0976c28a1bb2f73644268b7ffa7d2e08eab71f16a4"
url: "https://pub.dev"
source: hosted
- version: "2.5.0"
+ version: "2.5.4"
stack_trace:
dependency: transitive
description:
@@ -2139,10 +2081,10 @@ packages:
dependency: transitive
description:
name: state_notifier
- sha256: "8fe42610f179b843b12371e40db58c9444f8757f8b69d181c97e50787caed289"
+ sha256: b8677376aa54f2d7c58280d5a007f9e8774f1968d1fb1c096adcb4792fba29bb
url: "https://pub.dev"
source: hosted
- version: "0.7.2+1"
+ version: "1.0.0"
stream_channel:
dependency: transitive
description:
@@ -2187,10 +2129,10 @@ packages:
dependency: transitive
description:
name: synchronized
- sha256: "5fcbd27688af6082f5abd611af56ee575342c30e87541d0245f7ff99faa02c60"
+ sha256: "539ef412b170d65ecdafd780f924e5be3f60032a1128df156adad6c5b373d558"
url: "https://pub.dev"
source: hosted
- version: "3.1.0"
+ version: "3.1.0+1"
system_theme:
dependency: "direct main"
description:
@@ -2207,14 +2149,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.0.2"
- system_tray:
- dependency: "direct overridden"
- description:
- name: system_tray
- sha256: "087edb877f22f286d82d42f330fa640138c192e98aa9d20c2b83aa4e406bb432"
- url: "https://pub.dev"
- source: hosted
- version: "2.0.2"
term_glyph:
dependency: transitive
description:
@@ -2235,10 +2169,10 @@ packages:
dependency: transitive
description:
name: time
- sha256: "83427e11d9072e038364a5e4da559e85869b227cf699a541be0da74f14140124"
+ sha256: ad8e018a6c9db36cb917a031853a1aae49467a93e0d464683e029537d848c221
url: "https://pub.dev"
source: hosted
- version: "2.1.3"
+ version: "2.1.4"
timezone:
dependency: "direct main"
description:
@@ -2263,6 +2197,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.0"
+ tray_manager:
+ dependency: "direct main"
+ description:
+ name: tray_manager
+ sha256: e0ac9a88b2700f366b8629b97e8663b6ef450a2f169560a685dc167bfe9c9c29
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.2.2"
tuple:
dependency: transitive
description:
@@ -2271,6 +2213,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.2"
+ type_plus:
+ dependency: transitive
+ description:
+ name: type_plus
+ sha256: d5d1019471f0d38b91603adb9b5fd4ce7ab903c879d2fbf1a3f80a630a03fcc9
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.1"
typed_data:
dependency: transitive
description:
@@ -2315,74 +2265,74 @@ packages:
dependency: "direct main"
description:
name: url_launcher
- sha256: "47e208a6711459d813ba18af120d9663c20bdf6985d6ad39fe165d2538378d27"
+ sha256: "6ce1e04375be4eed30548f10a315826fd933c1e493206eab82eed01f438c8d2e"
url: "https://pub.dev"
source: hosted
- version: "6.1.14"
+ version: "6.2.6"
url_launcher_android:
dependency: transitive
description:
name: url_launcher_android
- sha256: b04af59516ab45762b2ca6da40fa830d72d0f6045cd97744450b73493fa76330
+ sha256: "360a6ed2027f18b73c8d98e159dda67a61b7f2e0f6ec26e86c3ada33b0621775"
url: "https://pub.dev"
source: hosted
- version: "6.1.0"
+ version: "6.3.1"
url_launcher_ios:
dependency: transitive
description:
name: url_launcher_ios
- sha256: "7c65021d5dee51813d652357bc65b8dd4a6177082a9966bc8ba6ee477baa795f"
+ sha256: "9149d493b075ed740901f3ee844a38a00b33116c7c5c10d7fb27df8987fb51d5"
url: "https://pub.dev"
source: hosted
- version: "6.1.5"
+ version: "6.2.5"
url_launcher_linux:
dependency: transitive
description:
name: url_launcher_linux
- sha256: b651aad005e0cb06a01dbd84b428a301916dc75f0e7ea6165f80057fee2d8e8e
+ sha256: ab360eb661f8879369acac07b6bb3ff09d9471155357da8443fd5d3cf7363811
url: "https://pub.dev"
source: hosted
- version: "3.0.6"
+ version: "3.1.1"
url_launcher_macos:
dependency: transitive
description:
name: url_launcher_macos
- sha256: b55486791f666e62e0e8ff825e58a023fd6b1f71c49926483f1128d3bbd8fe88
+ sha256: b7244901ea3cf489c5335bdacda07264a6e960b1c1b1a9f91e4bc371d9e68234
url: "https://pub.dev"
source: hosted
- version: "3.0.7"
+ version: "3.1.0"
url_launcher_platform_interface:
dependency: transitive
description:
name: url_launcher_platform_interface
- sha256: "95465b39f83bfe95fcb9d174829d6476216f2d548b79c38ab2506e0458787618"
+ sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029"
url: "https://pub.dev"
source: hosted
- version: "2.1.5"
+ version: "2.3.2"
url_launcher_web:
dependency: transitive
description:
name: url_launcher_web
- sha256: "2942294a500b4fa0b918685aff406773ba0a4cd34b7f42198742a94083020ce5"
+ sha256: "8d9e750d8c9338601e709cd0885f95825086bd8b642547f26bda435aade95d8a"
url: "https://pub.dev"
source: hosted
- version: "2.0.20"
+ version: "2.3.1"
url_launcher_windows:
dependency: transitive
description:
name: url_launcher_windows
- sha256: "95fef3129dc7cfaba2bc3d5ba2e16063bb561fc6d78e63eee16162bc70029069"
+ sha256: ecf9725510600aa2bb6d7ddabe16357691b6d2805f66216a97d1b881e21beff7
url: "https://pub.dev"
source: hosted
- version: "3.0.8"
+ version: "3.1.1"
uuid:
dependency: "direct main"
description:
name: uuid
- sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313"
+ sha256: "814e9e88f21a176ae1359149021870e87f7cddaf633ab678a5d2b0bff7fd1ba8"
url: "https://pub.dev"
source: hosted
- version: "3.0.7"
+ version: "4.4.0"
vector_math:
dependency: transitive
description:
@@ -2435,18 +2385,18 @@ packages:
dependency: transitive
description:
name: web
- sha256: "1d9158c616048c38f712a6646e317a3426da10e884447626167240d45209cbad"
+ sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27"
url: "https://pub.dev"
source: hosted
- version: "0.5.0"
+ version: "0.5.1"
web_socket_channel:
dependency: "direct main"
description:
name: web_socket_channel
- sha256: "1d8e795e2a8b3730c41b8a98a2dff2e0fb57ae6f0764a1c46ec5915387d257b2"
+ sha256: "58c6666b342a38816b2e7e50ed0f1e261959630becd4c879c4f26bfa14aa5a42"
url: "https://pub.dev"
source: hosted
- version: "2.4.4"
+ version: "2.4.5"
webdriver:
dependency: transitive
description:
@@ -2467,26 +2417,26 @@ packages:
dependency: transitive
description:
name: win32
- sha256: "9e82a402b7f3d518fb9c02d0e9ae45952df31b9bf34d77baf19da2de03fc2aaa"
+ sha256: "0a989dc7ca2bb51eac91e8fd00851297cfffd641aa7538b165c62637ca0eaa4a"
url: "https://pub.dev"
source: hosted
- version: "5.0.7"
+ version: "5.4.0"
win32_registry:
dependency: "direct main"
description:
name: win32_registry
- sha256: "41fd8a189940d8696b1b810efb9abcf60827b6cbfab90b0c43e8439e3a39d85a"
+ sha256: "10589e0d7f4e053f2c61023a31c9ce01146656a70b7b7f0828c0b46d7da2a9bb"
url: "https://pub.dev"
source: hosted
- version: "1.1.2"
+ version: "1.1.3"
window_manager:
dependency: "direct main"
description:
name: window_manager
- sha256: "6ee795be9124f90660ea9d05e581a466de19e1c89ee74fc4bf528f60c8600edd"
+ sha256: b3c895bdf936c77b83c5254bec2e6b3f066710c1f89c38b20b8acc382b525494
url: "https://pub.dev"
source: hosted
- version: "0.3.6"
+ version: "0.3.8"
window_size:
dependency: "direct main"
description:
@@ -2500,10 +2450,10 @@ packages:
dependency: transitive
description:
name: xdg_directories
- sha256: "589ada45ba9e39405c198fe34eb0f607cddb2108527e658136120892beac46d2"
+ sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d
url: "https://pub.dev"
source: hosted
- version: "1.0.3"
+ version: "1.0.4"
xml:
dependency: transitive
description:
@@ -2524,10 +2474,10 @@ packages:
dependency: "direct main"
description:
name: youtube_explode_dart
- sha256: "98fd11b51adbbca76cbdb17f560168f1d7a9835cecceea965f49eb1e5eed155c"
+ sha256: "12d32dffd8c85927eb46f7cf7a9dfce690edfe82134c08a90529c51eba58a85c"
url: "https://pub.dev"
source: hosted
- version: "2.0.2"
+ version: "2.2.0"
sdks:
dart: ">=3.3.0 <4.0.0"
- flutter: ">=3.16.0"
+ flutter: ">=3.19.2"
diff --git a/pubspec.yaml b/pubspec.yaml
index ee86c67c..dcb21259 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -3,7 +3,7 @@ description: Open source Spotify client that doesn't require Premium nor uses El
publish_to: "none"
-version: 3.5.0+29
+version: 3.6.0+30
homepage: https://spotube.krtirtho.dev
repository: https://github.com/KRTirtho/spotube
@@ -13,96 +13,89 @@ environment:
flutter: ">=3.10.0"
dependencies:
- args: ^2.3.2
+ args: ^2.5.0
async: ^2.9.0
- audio_service: ^0.18.9
- audio_session: ^0.1.18
+ audio_service: ^0.18.13
+ audio_service_mpris: ^0.1.3
+ audio_session: ^0.1.19
auto_size_text: ^3.0.0
- buttons_tabbar: ^1.3.6
+ buttons_tabbar: ^1.3.8
cached_network_image: ^3.3.1
- catcher_2: 1.0.0
+ catcher_2: ^1.2.4
collection: ^1.15.0
- cupertino_icons: ^1.0.5
curved_navigation_bar: ^1.0.3
dbus: ^0.7.8
- device_info_plus: ^9.1.2
+ device_info_plus: ^10.1.0
device_preview: ^1.1.0
- dio: ^5.4.1
- disable_battery_optimization: ^1.1.0+1
+ dio: ^5.4.3+1
+ disable_battery_optimization: ^1.1.1
duration: ^3.0.12
- envied: ^0.3.0
- file_selector: ^1.0.1
- fluentui_system_icons: ^1.1.189
+ envied: ^0.5.4+1
+ file_picker: ^8.0.0+1
+ file_selector: ^1.0.3
+ fluentui_system_icons: ^1.1.234
flutter:
sdk: flutter
flutter_cache_manager: ^3.3.0
- flutter_desktop_tools:
- git:
- url: https://github.com/KRTirtho/flutter_desktop_tools.git
- ref: 1f0bec3283626dcbd8ee2f54e238d096d8dea50e
flutter_displaymode: ^0.6.0
flutter_feather_icons: ^2.0.0+1
flutter_hooks: ^0.20.5
flutter_inappwebview: ^6.0.0
flutter_localizations:
sdk: flutter
- flutter_native_splash: ^2.3.10
- flutter_riverpod: ^2.4.10
+ flutter_native_splash: ^2.4.0
+ flutter_riverpod: ^2.5.1
flutter_secure_storage: ^9.0.0
flutter_svg: ^1.1.6
form_validator: ^2.1.1
fuzzywuzzy: ^1.1.6
go_router: 12.1.3 # Stuck on this https://github.com/flutter/flutter/issues/140869
- google_fonts: ^6.1.0
+ google_fonts: ^6.2.1
hive: ^2.2.3
hive_flutter: ^1.1.0
- hooks_riverpod: ^2.4.3
+ hooks_riverpod: ^2.5.1
html: ^0.15.1
http: ^1.2.0
- image_picker: ^1.0.4
+ image_picker: ^1.1.0
intl: ^0.18.0
- introduction_screen: ^3.0.2
+ introduction_screen: ^3.1.14
json_annotation: ^4.8.1
logger: ^2.0.2
- media_kit: ^1.1.3
- media_kit_libs_audio: ^1.0.3
+ media_kit: ^1.1.10+1
+ media_kit_libs_audio: ^1.0.4
metadata_god: ^0.5.2+1
mime: ^1.0.2
- package_info_plus: ^4.1.0
+ package_info_plus: ^6.0.0
palette_generator: ^0.3.3
path: ^1.8.0
- path_provider: ^2.0.8
- permission_handler: ^11.0.1
- piped_client:
- git:
- url: https://github.com/KRTirtho/piped_client.git
+ path_provider: ^2.1.3
+ permission_handler: ^11.3.1
+ piped_client: ^0.1.1
popover: ^0.3.0
scrobblenaut:
git:
url: https://github.com/KRTirtho/scrobblenaut.git
ref: dart-3-support
scroll_to_index: ^3.0.1
- sidebarx: ^0.16.3
- shared_preferences: ^2.2.2
+ sidebarx: ^0.17.1
+ shared_preferences: ^2.2.3
skeleton_text: ^3.0.1
- smtc_windows: ^0.1.1
+ smtc_windows: ^0.1.2
stroke_text: ^0.0.2
system_theme: ^2.1.0
titlebar_buttons: ^1.0.0
- url_launcher: ^6.1.7
- uuid: ^3.0.7
+ url_launcher: ^6.2.6
+ uuid: ^4.4.0
version: ^3.0.2
visibility_detector: ^0.4.0+2
- window_manager: ^0.3.1
+ window_manager: ^0.3.8
window_size:
git:
url: https://github.com/google/flutter-desktop-embedding.git
ref: a738913c8ce2c9f47515382d40827e794a334274
path: plugins/window_size
- youtube_explode_dart: ^2.0.1
- simple_icons: ^7.10.0
- audio_service_mpris: ^0.1.0
- file_picker: ^6.0.0
+ youtube_explode_dart: ^2.2.0
+ simple_icons: ^10.1.3
jiosaavn: ^0.1.0
draggable_scrollbar:
git:
@@ -116,9 +109,9 @@ dependencies:
url: https://github.com/Tommypop2/dart_discord_rpc.git
html_unescape: ^2.0.0
wikipedia_api: ^0.1.0
- skeletonizer: ^0.8.0
- app_links: ^3.5.0
- win32_registry: ^1.1.2
+ skeletonizer: ^1.1.1
+ app_links: ^4.0.1
+ win32_registry: ^1.1.3
flutter_sharing_intent: ^1.1.0
flutter_broadcasts: ^0.4.0
freezed_annotation: ^2.4.1
@@ -130,17 +123,18 @@ dependencies:
shelf: ^1.4.1
shelf_router: ^1.1.4
shelf_web_socket: ^1.0.4
- web_socket_channel: ^2.4.4
+ web_socket_channel: ^2.4.5
lrc: ^1.0.2
pub_api_client: ^2.4.0
pubspec_parse: ^1.2.2
timezone: ^0.9.2
crypto: ^3.0.3
+ local_notifier: ^0.1.6
+ tray_manager: ^0.2.2
dev_dependencies:
build_runner: ^2.4.9
- envied_generator: ^0.3.0+3
- flutter_distributor: ^0.0.2
+ envied_generator: ^0.5.4+1
flutter_gen_runner: ^5.4.0
flutter_launcher_icons: ^0.13.1
flutter_lints: ^3.0.1
@@ -150,12 +144,12 @@ dev_dependencies:
sdk: flutter
hive_generator: ^2.0.0
json_serializable: ^6.6.2
- freezed: ^2.4.6
- custom_lint: ^0.5.11
- riverpod_lint: ^2.1.1
+ freezed: ^2.5.2
+ custom_lint: ^0.6.4
+ riverpod_lint: ^2.3.10
dependency_overrides:
- system_tray: 2.0.2
+ uuid: ^4.4.0
flutter:
generate: true
diff --git a/untranslated_messages.json b/untranslated_messages.json
index 3696d52e..9e26dfee 100644
--- a/untranslated_messages.json
+++ b/untranslated_messages.json
@@ -1,204 +1 @@
-{
- "ar": [
- "enable_connect",
- "enable_connect_description",
- "devices",
- "select",
- "connect_client_alert",
- "this_device",
- "remote"
- ],
-
- "bn": [
- "enable_connect",
- "enable_connect_description",
- "devices",
- "select",
- "connect_client_alert",
- "this_device",
- "remote"
- ],
-
- "ca": [
- "enable_connect",
- "enable_connect_description",
- "devices",
- "select",
- "connect_client_alert",
- "this_device",
- "remote"
- ],
-
- "de": [
- "enable_connect",
- "enable_connect_description",
- "devices",
- "select",
- "connect_client_alert",
- "this_device",
- "remote"
- ],
-
- "es": [
- "enable_connect",
- "enable_connect_description",
- "devices",
- "select",
- "connect_client_alert",
- "this_device",
- "remote"
- ],
-
- "fa": [
- "enable_connect",
- "enable_connect_description",
- "devices",
- "select",
- "connect_client_alert",
- "this_device",
- "remote"
- ],
-
- "fr": [
- "enable_connect",
- "enable_connect_description",
- "devices",
- "select",
- "connect_client_alert",
- "this_device",
- "remote"
- ],
-
- "hi": [
- "enable_connect",
- "enable_connect_description",
- "devices",
- "select",
- "connect_client_alert",
- "this_device",
- "remote"
- ],
-
- "it": [
- "enable_connect",
- "enable_connect_description",
- "devices",
- "select",
- "connect_client_alert",
- "this_device",
- "remote"
- ],
-
- "ja": [
- "enable_connect",
- "enable_connect_description",
- "devices",
- "select",
- "connect_client_alert",
- "this_device",
- "remote"
- ],
-
- "ko": [
- "enable_connect",
- "enable_connect_description",
- "devices",
- "select",
- "connect_client_alert",
- "this_device",
- "remote"
- ],
-
- "ne": [
- "enable_connect",
- "enable_connect_description",
- "devices",
- "select",
- "connect_client_alert",
- "this_device",
- "remote"
- ],
-
- "nl": [
- "enable_connect",
- "enable_connect_description",
- "devices",
- "select",
- "connect_client_alert",
- "this_device",
- "remote"
- ],
-
- "pl": [
- "enable_connect",
- "enable_connect_description",
- "devices",
- "select",
- "connect_client_alert",
- "this_device",
- "remote"
- ],
-
- "pt": [
- "enable_connect",
- "enable_connect_description",
- "devices",
- "select",
- "connect_client_alert",
- "this_device",
- "remote"
- ],
-
- "ru": [
- "enable_connect",
- "enable_connect_description",
- "devices",
- "select",
- "connect_client_alert",
- "this_device",
- "remote"
- ],
-
- "th": [
- "choose_your_language",
- "enable_connect",
- "enable_connect_description",
- "devices",
- "select",
- "connect_client_alert",
- "this_device",
- "remote"
- ],
-
- "uk": [
- "enable_connect",
- "enable_connect_description",
- "devices",
- "select",
- "connect_client_alert",
- "this_device",
- "remote"
- ],
-
- "vi": [
- "friends",
- "no_lyrics_available",
- "enable_connect",
- "enable_connect_description",
- "devices",
- "select",
- "connect_client_alert",
- "this_device",
- "remote"
- ],
-
- "zh": [
- "enable_connect",
- "enable_connect_description",
- "devices",
- "select",
- "connect_client_alert",
- "this_device",
- "remote"
- ]
-}
+{}
\ No newline at end of file
diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc
index d8a9db29..57542dec 100644
--- a/windows/flutter/generated_plugin_registrant.cc
+++ b/windows/flutter/generated_plugin_registrant.cc
@@ -16,7 +16,7 @@
#include
#include
#include
-#include
+#include
#include
#include
#include
@@ -42,8 +42,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) {
registry->GetRegistrarForPlugin("ScreenRetrieverPlugin"));
SystemThemePluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("SystemThemePlugin"));
- SystemTrayPluginRegisterWithRegistrar(
- registry->GetRegistrarForPlugin("SystemTrayPlugin"));
+ TrayManagerPluginRegisterWithRegistrar(
+ registry->GetRegistrarForPlugin("TrayManagerPlugin"));
UrlLauncherWindowsRegisterWithRegistrar(
registry->GetRegistrarForPlugin("UrlLauncherWindows"));
WindowManagerPluginRegisterWithRegistrar(
diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake
index 90292744..6a0c7723 100644
--- a/windows/flutter/generated_plugins.cmake
+++ b/windows/flutter/generated_plugins.cmake
@@ -13,7 +13,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
permission_handler_windows
screen_retriever
system_theme
- system_tray
+ tray_manager
url_launcher_windows
window_manager
window_size