[Release] v4.1.0+40100005 (#274)

NEW
- [Sonarr/Queue] Check and update the queue in the background every 60 seconds
- [Sonarr/Queue] Ability to view and manage your queue
- [Sonarr/Queue] Ability to delete an item in the queue
- [Sonarr/Sorting] Ability to set the initial sorting direction alongside the sorting type for series and releases

TWEAKS
- [Radarr] Use Radarr v3 icon across the UI
- [Settings/Dialogs] Small tweaks and additional notes for entering hosts and passwords
- [Settings/Host Dialog] Add validator on host to ensure user adds http:// or https://

FIXES
- [UI/Checkbox] Fix overly vibrant checkbox background
- [Sonarr/Add] Fix possible grey screen when adding a show with no seasons yet
- [Flutter] Upgraded Flutter & Packages
This commit is contained in:
Jagandeep Brar
2020-12-01 12:50:06 -06:00
committed by GitHub
parent 149e89853e
commit 983f5bf7ff
30 changed files with 951 additions and 51 deletions

432
CHANGELOG.md Normal file
View File

@@ -0,0 +1,432 @@
# LunaSea Changelog
## [Beta/TestFlight] v4.1.0 (40100005)
#### NEW
- `[Sonarr/Queue]` Check and update the queue in the background every 60 seconds
- `[Sonarr/Queue]` Ability to view and manage your queue
- `[Sonarr/Queue]` Ability to delete an item in the queue
- `[Sonarr/Sorting]` Ability to set the initial sorting direction alongside the sorting type for series and releases
#### TWEAKS
- `[Radarr]` Use Radarr v3 icon across the UI
- `[Settings/Dialogs]` Small tweaks and additional notes for entering hosts and passwords
- `[Settings/Host Dialog]` Add validator on host to ensure user adds http:// or https://
#### FIXES
- `[UI/Checkbox]` Fix overly vibrant checkbox background
- `[Sonarr/Add]` Fix possible grey screen when adding a show with no seasons yet
- `[Flutter]` Upgraded Flutter & Packages
---
## [Beta/TestFlight] v4.1.0 (40100004)
#### FIXES
- `[Sonarr/v2]` Fix grey screen when attempting to add a new series
#### TWEAKS
- `[Packages]` Updated transitive Flutter packages
---
## [Beta/TestFlight] v4.1.0 (40100003)
#### NEW
- `[Sonarr]` Ability to manage your tags
- `[Sonarr/Add]` Ability to set tags when adding a new series
- `[Sonarr/Edit]` Ability to update tags when editing a series
#### FIXES
- `[Routing]` Fixed some issues with routing
- `[Sonarr/Add]` After adding a series, hitting back will now show the series as added
---
## [Beta/TestFlight] v4.1.0 (40100002)
#### NEW
- `[Images]` Ability to set (or entirely disable) the opacity of the background image for cards
- `[Sonarr]` Ability to set the default sorting type for series and releases
- `[Tautulli/Activity]` Show the ETA for when the session will be completed
- `[Tautulli/Activity]` Show if the hardware transcoding is being used on the stream
#### FIXES
- `[Networking]` Ensure that insecure (HTTP/80) connections are allowed at the platform-level
- `[Flutter]` Upgraded Flutter & Packages
---
## [Beta/TestFlight] v4.1.0 (40100001)
#### NEW
- `[Networking]` Strict TLS/SSL validation is now disabled globally
- `[Routing]` Hold the AppBar back button to pop back to the home page of the module
- `[Settings/Sonarr]` Toggle to enable Sonarr v3 features
- `[Sonarr]` Complete rewrite of Sonarr
- `[Sonarr]` State is now held across module switches
- `[Sonarr/Overview]` View tags applied to series
- `[Sonarr/Catalogue]` (v3 only) Ability to set and update language profile
- `[Sonarr/Catalogue]` Ability to view all, only monitored, or only unmonitored series
- `[Sonarr/Releases]` (v3 only) Ability to interactively search for season packs
- `[Sonarr/Releases]` Ability to view all, only approved, or only rejected releases
#### TWEAKS
- `[Settings]` Removed all toggles for strict TLS
- `[Sonarr]` Many tweaks to Sonarr's design
- `[Sonarr/Add]` (v3 only) Tapping an already-added series will take you to the series page
- `[Sonarr/Add]` Automatically navigate to newly added series
- `[Sonarr/Series]` Toggling monitored state of series has now been moved to the edit prompt
#### FIXES
- `[Images]` Images will now load for invalid/self-signed certificates
- `[Tautulli/Activity]` Fix grey screen for music activity
- `[TextField]` Fix TextField actions (cut, copy, paste, etc.) not showing
- `[Timestamps]` Fix 12:xx AM being shown as 00:xx AM
- `[Everything]` Additional small bug fixes
---
## [Stable/Production] v4.0.0 (400102)
#### NEW
- `[Module]` Tautulli support
- `[Calendar]` Ability to set how many days in the past and future to fetch calendar entries for
- `[Drawer]` Categorical folders are now optional
- `[Drawer]` If using folders, ability to set the initial expanded state
- `[Locale]` Ability to use 24 hour timestamps
- `[Quick Actions]` Ability to set upto four homescreen quick actions
- `[Search]` Ability to set custom headers for individual indexers
- `[Settings]` Complete overhaul of the settings
- `[Settings/Resources]` (iOS) Added link to join TestFlight
#### TWEAKS
- `[Home/Calendar]` Separate calendar view type into its own preference
- `[Home/Calendar]` Show no modules enabled message when there are no automation modules enabled, not just no modules overall
- `[Home/Calendar]` Default past and future days is now 14 days for each
- `[Images]` Images are no longer cached to the device storage to heavily improve performance & reduce crashing on older/lower-end devices
- `[Images]` Fetch images at specific resolutions instead of full resolution to reduce network performance and decrease memory pressure
- `[Search]` Improved detection of adult categories
- `[Settings]` Settings now replaces the active module/route and shows the drawer on the base route
- `[Settings/System]` Removed clear image cache tile
- `[UI]` Added new loading animation design
#### FIXES
- `[Flutter]` Updated packages & Flutter
- `[General]` Many small bug fixes
- `[LunaSea]` Many behind the scenes changes to reduce memory pressure
- `[LunaSea]` Heavy improvements and fixes to the navigation routing
- `[Settings/Logs]` Logs could be shown in reverse order
- `[Text]` Fixed "squished" text on iOS 14 and higher devices
---
## [Stable/Production] v3.3.0 (330002)
#### NEW
- `[Home/Calendar]` New "schedule" view
- `[Home/Modules]` Option to use module "brand colour" or the LunaSea list colours
- `[Search]` Option to hide adult categories
- `[-arr/Catalogue]` Ability to sort by date added
- `[-arr/Search]` Show the indexer/tracker on the collapsed tile
#### TWEAKS
- None
#### FIXES
- `[Sonarr]` Fixed multiple errors related to parsing fetched episode data
- `[Everything]` Multiple smaller crash/error fixes
---
## [Stable/Production] v3.2.0 (320003)
#### NEW
- `[Drawer]` Add the LunaSea logo to the header
- `[Logging]` Integrated Sentry, an open-source exception/crash log aggregation tool
- `[Settings/System]` Added toggle (under system -> advanced) to disable Sentry logging
#### TWEAKS
- `[System]` Implemented new image caching backend
- `[APIs]` Improved exception logging
- `[Logging]` Improved on-device logger to have more useful stack traces
#### FIXES
- `[-arr/Details]` Fixed crash related to state management
- `[radarr/Add]` Fixed crash when a searched movie does not have a minimum availability value available
---
## [Stable/Production] v3.1.0 (310004)
#### NEW
- `[Settings/Resources]` Added Discord invite link for official server
- `[-arr]` Ability to search and enter interactive search from all upcoming and missing pages
- `[-arr/Add]` Ability to jump directly into newly added content from toast notification
- `[Radarr/Delete]` Ability to add to exclusion list when deleting content
- `[Clients]` Hide and show queue pause/start FAB on scroll
- `[Clients/History]` History tiles are now expandable in-line
- `[SABnzbd/Statistics]` Show both temporary and final storage space
- `[Calendar]` Ability to search/enter interactive search directly from calendar tiles
#### TWEAKS
- `[Development]` Updated Flutter packages
#### FIXES
- `[API/Host]` Correctly handle cases where host ends with a forward slash
---
## [Stable/Production] v3.0.0 (300100)
#### NEW
- `[Search]` Releases are now shown as an expandable tile
- `[Search/Category Results]` Ability to sort and filter results
- `[Search/Search Results]` Ability to sort search results
- `[-rr/Catalogue]` Many additional sorting options
- `[-rr/Releases]` Releases are now shown as an expandable tile
- `[-rr/Releases]` Ability to sort, hide, and filter releases
- `[Sonarr/Add]` Ability to set initial episode monitoring state
- `[Sonarr/Episodes]` Episodes are now shown as an expandable tile
- `[Radarr/Releases]` Shows custom format tags
- `[Clients]` FAB icon animates between queue state
- `[Images]` Ability to clear network image cache
- `[UI/AMOLED Theme]` Optional setting to add subtle border
#### TWEAKS
- `[Changelog]` Removed integrated changelog, redirects to documentation changelog
- `[-rr]` Use the term "Interactive" instead of "Manual" for search
- `[-rr/Links]` Normalize size of images
- `[Sonarr/Upcoming]` Now shows dates in-line as a styled header
- `[Sonarr/Season View]` Now shows season number in-line as a styled header
- `[UI/Font]` Adjusted font size across entire application
- `[UI/Dropdowns]` Change dropdowns to popup menus
- `[UI]` Rounder radius around tiles, popups, etc.
#### FIXES
- `[Home/Calendar]` Row height is now statically set to prevent huge calendar on larger displays
- `[Sonarr/Seasons]` Fixed crash related to seasons with no statistics data for percentage of season completion
- `[Sonarr/Episodes]` Episode numbers greater than 100 could cause a line-break
- `[Sonarr/Episodes]` Fixed/safe-guarded layout crash on incomplete episode data received
- `[Sonarr/Queue]` Safe-guarded Sonarr queue results when results are null
- `[Snackbar]` Snackbar wouldn't adopt AMOLED styling when enabled
- `[State]` Fixed crashes caused by setting the state of an unmounted widget
---
## [Stable/Production] v2.3.0 (230004)
#### NEW
- `[Module]` Wake on LAN support
- `[Settings/Modules]` Ability to set custom headers to be attached to module requests
- `[Settings/Changelog]` Changelog is now displayed as a route, not a dialog
- `[UX]` Hitting the back button on apex/primary routes will now open the drawer instead of closing the application
- `[UX]` Enable landscape mode for iPhones
#### TWEAKS
- `[-rr/Details]` Removed sliver AppBar and fanart as it caused unwanted scrolling interference (A revamped overview page in the future will bring back the fanart images)
- `[-rr/Details]` Switched from AppBar tabs to bottom navigation bar
- `[-rr/Release]` Do not show warning message when triggering a release download from details page on rejected release
- `[Dialogs]` Reimplemented all dialogs
- `[Dialogs]` Keyboard type is now set for all inputs
- `[Dialogs]` All inputs are now validated (to some extent) and can be submitted via the Keyboard
#### FIXES
- `[SnackBar]` SnackBar could cause UI locking when doing swipe-back gestures
---
## [Stable/Production] v2.2.0 (220003)
#### NEW
- `[Donations]` Added donation IAPs
- `[Profiles]` Added rapid-profile switcher
- `[Settings]` Added license attributions
- `[Settings]` Added feedback link
- `[-rr/Add]` Search bar will now be autofocused
- `[SABnzbd]` Added statistics for individual servers
- `[NZBGet]` Option to use basic authentication instead of URL-encoded authentication
#### TWEAKS
- `[UI]` Removed custom letter spacing
- `[Settings]` Added subheaders
#### FIXES
- `[Database]` Cleanly exit on clean application exit to prevent corruption
---
## [Stable/Production] v2.1.0 (66)
#### NEW
- `[Branding]` New icon & splash screen
- `[Links]` Ability to set which browser you open links in (iOS only)
- `[Home/Calendar]` Ability to set starting day of week
- `[Home/Calendar]` Ability to set starting calendar size
- `[Home/Calendar]` Ability to enable and disable specific modules that show up in the calendar
- `[Appearance/Theme]` Option to enable AMOLED black theme
- `[Platform]` LunaSea is now buildable & available for Android
#### TWEAKS
- `[Settings]` Redesign of settings page
- `[General]` Use the term "Modules" instead of "Services"
- `[-rr/Details]` Background image header/appbar is now collapsed by default
- `[-rr/Details]` Left align title to match the rest of LunaSea
#### FIXES
- `[Sonarr]` Toast for toggling season monitor state would show monitor status of the series, not the season
- `[Settings/Backup]` Backing up your configuration would always fail
- `[Search]` Would show an empty screen if you deleted all indexers while search is open
---
## [Stable/Production] v2.0.1 (55)
#### NEW
- `[SABnzbd]` Ability to upload .rar & .gz archives
- `[-rr/Add]` All configurable values are now stored in cold database, persisting between sessions
- `[-rr/Add]` Root folders now also show available space for the folder
- `[Search]` When sending an NZB to a client, there is now an action in the toast to jump directly to the respective client
- `[Automation/Search]` When downloading a release manually, there is now an action in the toast to pop back to the main screen of the automation service
- `[Settings]` Ability to disable SSL/TLS validation for all services
- `[HTTP]` With the above, support for self-signed SSL certificates
#### TWEAKS
- `[Descriptions]` Adjusted alignment and consistency when no summary is available
- `[Search]` Removed redundant “Sending” toast since it very quickly gets covered by the follow-up toast
- `[Automation]` Edit content prompt now shows full title of the content
- `[Clients]` Opening the edit menu now shows the full title of the job
- `[UI]` Tweaked design of content headers
- `[Settings]` Added headers to automation and client pages to separate regular and advanced configuration options
#### FIXES
- `[HTTP]` Safer handling of redirects
- `[Routes]` Make route changes asynchronous to help minimize stutters
- `[Radarr/Add]` Fixed wrong title for minimum availability card
- `[Restore Configuration]` Error message had typos
- `[UI]` Fixed uneven font sizing in some prompts
- `[NZBGet/SABnzbd]` Failure on uploading an NZB would show no error message
---
## [Stable/Production] v2.0.0 (333)
#### NEW
- `[iOS]` Built for iOS 13.4
- `[Indexers/Search]` Full support for browsing and searching Newznab-based indexers!
- `[Indexers/Search]` Support for NZBHydra2
- `[Indexers/Search]` Download NZB files directly to your device
- `[Indexers/Search]` Send NZB files directly from the indexer to your client of choice
- `[-rr/Catalogue]` Catalogue search bar is now stickied
- `[-rr/History]` Ability to enter content
- `[-rr/Add]` More information (year, seasons, etc.) shown in result tiles
- `[NZBGet]` Ability to search through fetched history
- `[SABnzbd]` Ability to search through fetched history
- `[Settings/Configuration]` Ability to clear configuration
- `[Drawer]` Ability to switch profiles in navigation Drawer
- `[Snackbar]` New snackbar style, design, and formatting
- `[Everything]` All services now dynamically reload on profile changes
#### TWEAKS
- `[Everything]` Reimplemented... everything
- `[Everything]` Moved away from FABs (where possible) to buttons
- `[Navigation]` Ability to swipe left and right between bottom navigation tabs (except Settings)
- `[Navigation Bar]` Slightly redesigned
- `[Home/Summary]` Redesigned summary page
- `[Home/Summary]` Removed fetching of series count, movie count, and artist count
- `[Home/Calendar]` Now only shows 1 dot for each day instead of 3
- `[Home/Calendar]` Highlights today as well as selected day
- `[Home/Calendar]` Now shows the day of the week on the calendar
- `[Home/Calendar]` Now defaults to showing 1 week (swipe down to show two weeks or one month)
- `[Settings]` No longer a need to save configuration settings, everything is saved automatically
- `[Search Bar]` "X" to clear search bars
- `[-rr/Catalogue]` Sorting now scrolls back to top
- `[-rr/Catalogue]` Moved hide unmonitored button to stickied search bar
- `[-rr/Add]` Selected profile, folders, etc. are stored in state until application is closed or profile is switched
- `[-rr/Images]` Images now show placeholder, transition to real content on load
- `[Sonarr/Episodes]` Multi-select episodes with single tap anywhere on tile, now highlighted for easier distinction
- `[SABnzbd]` Limit queue to first 100 results
- `[SABnzbd]` Lowered refresh rate to 2 seconds from 1 second
- `[NZBGet]` Limit queue to first 100 results
- `[NZBGet]` Lowered refresh rate to 2 seconds from 1 second
- `[UI]` Reduced elevation of UI in general
#### FIXES
- `[Sonarr/Search]` Searching for an entire season now executes a season search instead of individual episode searches
- `[Logs]` Fixed bug where logs could not load in some cases and always show "Logs Not Found"
- `[Radarr/Search]` Now correctly retains search state to prevent needless researching & API hits
- `[Configuration]` Deleting or renaming "default" profile could cause a new "default" profile to be created on next launch
---
## [Stable/Production] v1.1.0 (44)
#### NEW
- `[Home]` Calendar view for upcoming -rr content
- `[Sonarr]` Ability to toggle single episode monitored status
- `[Sonarr]` Ability to delete file
- `[Radarr]` Split missing tab into missing and upcoming
- `[-rr]` Long-press tile on non-catalogue pages to view catalogue entry
- `[-rr]` Ability to delete files when deleting catalogue entries
- `[Documentation]` Added a link to WIP documentation
#### FIXES
- `[Prompts]` All prompts now use the correct colour ordering
- `[NZBGet]` Adjusted authentication method to interfere less with custom auth setups
#### TWEAKS
- `[Drawer]` Dropdown groups are open by default until more services are added
- `[Settings]` Minor tile shuffling and rewording
- `[Navigation]` New style for the navigation bars
- `[Navigation]` Added custom icons to navigation bars
- `[Releases]` Easier to differentiate the release's protocol
---
## [Stable/Production] v1.0.0 (33)
#### NEW
- `[-rr]` When adding new content, checks if content is already in your library
- `[-rr]` Ability to sort catalogue by size of alphabetical
- `[Settings]` Ability to rename a profile
- `[SAB/NZBGet]` Ability to pause the queue for some amount of time
- `[NZBGet]` Ability to filter out successful history entries
#### FIXES
- `[Radarr]` Fetching quality profiles could fail
- `[SAB/NZBGet]` Percentage calculation could fail causing a grey screen
- `[SAB/NZBGet]` Connection error now cancels timer until manual refresh (cleaner logs)
#### TWEAKS
- `[Build]` Adjusted how build number is presented
- `[Sonarr]` Now shows size on disk on catalogue page
- `[Lidarr]` Now shows size on disk on catalogue page
- `[Settings]` Successful connection test now also triggers save
- `[Settings]` Save button is now more obvious/clear
- `[Settings]` Adjusted and added more tips when adding hosts

View File

@@ -31,8 +31,8 @@ LunaSea even comes with support for multiple instances of applications using pro
1. A MacOS Machine
2. An AppleID account (does not require developer account)
3. [Flutter Framework (Beta Channel)](https://flutter.dev/)
4. [XCode 11.4 or Higher](https://apps.apple.com/ca/app/xcode/id497799835?mt=12)
3. [Flutter Framework (Stable Channel)](https://flutter.dev/)
4. [XCode](https://apps.apple.com/ca/app/xcode/id497799835?mt=12)
5. [Developer Certificate Configured](https://github.com/LunaSeaApp/LunaSea/wiki/Setup-of-Development-Certificate)
#### Developing
@@ -72,8 +72,8 @@ LunaSea even comes with support for multiple instances of applications using pro
#### Requirements
1. Android SDK/Android Studio Installed & Configured
2. [Flutter Framework (Beta Channel)](https://flutter.dev/)
1. [Android SDK/Android Studio Installed & Configured](https://developer.android.com/studio)
2. [Flutter Framework (Stable Channel)](https://flutter.dev/)
3. [Keystore Configured](https://github.com/LunaSeaApp/LunaSea/wiki/Configure-Keystore)
#### Developing

Binary file not shown.

View File

@@ -107,4 +107,4 @@ SPEC CHECKSUMS:
PODFILE CHECKSUM: d583357f6c19d22241654320250048fb085838b3
COCOAPODS: 1.9.3
COCOAPODS: 1.10.0

View File

@@ -5,7 +5,7 @@ import 'package:lunasea/core.dart';
class LunaDialogs {
LunaDialogs._();
static Future<List<dynamic>> editText(BuildContext context, String title, { String prefill = '' }) async {
static Future<List<dynamic>> editText(BuildContext context, String title, { String prefill = '', List<TextSpan> extraText }) async {
bool _flag = false;
final _formKey = GlobalKey<FormState>();
final _textController = TextEditingController()..text = prefill;
@@ -27,6 +27,7 @@ class LunaDialogs {
),
],
content: [
if((extraText?.length ?? 0) != 0) LSDialog.richText(children: extraText),
Form(
key: _formKey,
child: LSDialog.textFormInput(
@@ -37,7 +38,7 @@ class LunaDialogs {
),
),
],
contentPadding: LSDialog.inputDialogContentPadding(),
contentPadding: (extraText?.length ?? 0) == 0 ? LSDialog.inputDialogContentPadding() : LSDialog.inputTextDialogContentPadding(),
);
return [_flag, _textController.text];
}

View File

@@ -23,6 +23,7 @@ class LunaTheme {
splashColor: LunaColours.splash,
dialogBackgroundColor: LunaColours.secondary,
dividerColor: LunaColours.accent.withAlpha(0),
toggleableActiveColor: LunaColours.accent,
dividerTheme: DividerThemeData(
color: LunaColours.accent,
indent: 100.0,
@@ -65,6 +66,7 @@ class LunaTheme {
splashColor: LunaColours.splash,
dialogBackgroundColor: Colors.black,
dividerColor: LunaColours.accent.withAlpha(0),
toggleableActiveColor: LunaColours.accent,
dividerTheme: DividerThemeData(
color: LunaColours.accent,
indent: 72.0,

View File

@@ -37,4 +37,5 @@ class CustomIcons {
static const IconData discord = IconData(0xe81c, fontFamily: _kFontFam, fontPackage: _kFontPkg);
static const IconData tautulli = IconData(0xe81d, fontFamily: _kFontFam, fontPackage: _kFontPkg);
static const IconData plex = IconData(0xe81e, fontFamily: _kFontFam, fontPackage: _kFontPkg);
static const IconData radarr = IconData(0xe81f, fontFamily: _kFontFam, fontPackage: _kFontPkg);
}

View File

@@ -11,7 +11,7 @@ class RadarrConstants {
name: 'Radarr',
description: 'Manage Movies',
settingsDescription: 'Configure Radarr',
icon: CustomIcons.movies,
icon: CustomIcons.radarr,
route: '/radarr',
color: Color(0xFFFEC333),
);

View File

@@ -31,14 +31,18 @@ class SettingsDialogs {
content: [
LSDialog.richText(
children: [
LSDialog.textSpanContent(text: '\tThis is the URL in which you access the web GUI for the service\n'),
LSDialog.textSpanContent(text: '\tYou must include either '),
LSDialog.textSpanContent(text: '${Constants.TEXT_BULLET}\tThis is the URL in which you access the web GUI for the service\n'),
LSDialog.textSpanContent(text: '${Constants.TEXT_BULLET}\tYou must include either '),
LSDialog.bolded(text: 'http://'),
LSDialog.textSpanContent(text: ' or '),
LSDialog.bolded(text: 'https://\n'),
LSDialog.textSpanContent(text: '\tWhen not using a reverse proxy, please include the port: '),
LSDialog.textSpanContent(text: '${Constants.TEXT_BULLET}\tDo not use '),
LSDialog.bolded(text: 'localhost'),
LSDialog.textSpanContent(text: ' or '),
LSDialog.bolded(text: '127.0.0.1\n'),
LSDialog.textSpanContent(text: '${Constants.TEXT_BULLET}\tWhen not using a reverse proxy, please include the port: '),
LSDialog.bolded(text: 'url:port\n'),
LSDialog.textSpanContent(text: '\tTo add basic authentication, please set a custom header in the advanced section'),
LSDialog.textSpanContent(text: '${Constants.TEXT_BULLET}\tTo add basic authentication, please set a custom header in the advanced section'),
],
),
Form(
@@ -48,7 +52,14 @@ class SettingsDialogs {
title: title,
keyboardType: TextInputType.url,
onSubmitted: (_) => _setValues(true),
validator: (_) => null,
validator: (value) {
// Allow empty value
if(value == '') return null;
// Test for https:// or http://
RegExp exp = RegExp(r"^(http|https)://", caseSensitive: false);
if(exp.hasMatch(value)) return null;
return 'Host must include http:// or https://';
},
),
),
],

View File

@@ -2,7 +2,7 @@ import 'dart:io';
import 'package:fluro/fluro.dart';
import 'package:flutter/material.dart';
import 'package:lunasea/core.dart';
import 'package:lunasea/modules/settings.dart';
import 'package:lunasea/modules.dart';
class SettingsCustomizationRouter {
static const ROUTE_NAME = '/settings/customization';
@@ -107,9 +107,9 @@ class _State extends State<_SettingsCustomizationRoute> with AutomaticKeepAliveC
onTap: () async => SettingsCustomizationLidarrRouter.navigateTo(context),
),
LSCardTile(
title: LSTitle(text: 'Radarr'),
title: LSTitle(text: RadarrConstants.MODULE_MAP.name),
subtitle: LSSubtitle(text: 'Radarr Customizations'),
trailing: LSIconButton(icon: CustomIcons.movies),
trailing: LSIconButton(icon: RadarrConstants.MODULE_MAP.icon),
onTap: () async => SettingsCustomizationRadarrRouter.navigateTo(context),
),
LSCardTile(

View File

@@ -67,9 +67,11 @@ class _State extends State<_SettingsCustomizationSonarrRoute> {
List<Widget> get _defaultSorting => [
LSHeader(
text: 'Default Sorting',
subtitle: 'Choose the default sorting type for sortable lists',
subtitle: 'Choose default sorting options for sortable lists',
),
SettingsCustomizationSonarrDefaultSortingReleasesTile(),
SettingsCustomizationSonarrDefaultSortingReleasesAscendingTile(),
SettingsCustomizationSonarrDefaultSortingSeriesTile(),
SettingsCustomizationSonarrDefaultSortingSeriesAscendingTile(),
];
}

View File

@@ -1,4 +1,6 @@
export 'widgets/default_pages_home.dart';
export 'widgets/default_pages_series_details.dart';
export 'widgets/default_sorting_releases_ascending.dart';
export 'widgets/default_sorting_releases.dart';
export 'widgets/default_sorting_series_ascending.dart';
export 'widgets/default_sorting_series.dart';

View File

@@ -7,7 +7,7 @@ class SettingsCustomizationSonarrDefaultSortingReleasesTile extends StatelessWid
Widget build(BuildContext context) => ValueListenableBuilder(
valueListenable: Database.lunaSeaBox.listenable(keys: [SonarrDatabaseValue.DEFAULT_SORTING_RELEASES.key]),
builder: (context, box, _) => LSCardTile(
title: LSTitle(text: 'Releases'),
title: LSTitle(text: 'Releases Category'),
subtitle: LSSubtitle(text: (SonarrDatabaseValue.DEFAULT_SORTING_RELEASES.data as SonarrReleasesSorting).readable),
trailing: LSIconButton(icon: Icons.arrow_forward_ios),
onTap: () async => _defaultSorting(context),
@@ -20,8 +20,8 @@ class SettingsCustomizationSonarrDefaultSortingReleasesTile extends StatelessWid
if(_values[0]) {
SonarrDatabaseValue.DEFAULT_SORTING_RELEASES.put(SonarrReleasesSorting.values[_values[1]]);
// Reset the state of the sorting
context.read<SonarrState>().releasesSortType = SonarrReleasesSorting.values[_values[1]];
context.read<SonarrState>().releasesSortAscending = true;
context.read<SonarrState>().releasesSortType = SonarrDatabaseValue.DEFAULT_SORTING_RELEASES.data;
context.read<SonarrState>().releasesSortAscending = SonarrDatabaseValue.DEFAULT_SORTING_RELEASES_ASCENDING.data;
}
}
}

View File

@@ -0,0 +1,26 @@
import 'package:flutter/material.dart';
import 'package:lunasea/core.dart';
import 'package:lunasea/modules/sonarr.dart';
class SettingsCustomizationSonarrDefaultSortingReleasesAscendingTile extends StatelessWidget {
@override
Widget build(BuildContext context) => ValueListenableBuilder(
valueListenable: Database.lunaSeaBox.listenable(keys: [SonarrDatabaseValue.DEFAULT_SORTING_RELEASES_ASCENDING.key]),
builder: (context, box, _) => LSCardTile(
title: LSTitle(text: 'Releases Sort Direction'),
subtitle: LSSubtitle(text: SonarrDatabaseValue.DEFAULT_SORTING_RELEASES_ASCENDING.data
? 'Ascending'
: 'Descending'
),
trailing: Switch(
value: SonarrDatabaseValue.DEFAULT_SORTING_RELEASES_ASCENDING.data,
onChanged: (value) {
SonarrDatabaseValue.DEFAULT_SORTING_RELEASES_ASCENDING.put(value);
// Reset the state of the sorting
context.read<SonarrState>().releasesSortType = SonarrDatabaseValue.DEFAULT_SORTING_RELEASES.data;
context.read<SonarrState>().releasesSortAscending = SonarrDatabaseValue.DEFAULT_SORTING_RELEASES_ASCENDING.data;
},
),
),
);
}

View File

@@ -7,7 +7,7 @@ class SettingsCustomizationSonarrDefaultSortingSeriesTile extends StatelessWidge
Widget build(BuildContext context) => ValueListenableBuilder(
valueListenable: Database.lunaSeaBox.listenable(keys: [SonarrDatabaseValue.DEFAULT_SORTING_SERIES.key]),
builder: (context, box, _) => LSCardTile(
title: LSTitle(text: 'Series'),
title: LSTitle(text: 'Series Category'),
subtitle: LSSubtitle(text: (SonarrDatabaseValue.DEFAULT_SORTING_SERIES.data as SonarrSeriesSorting).readable),
trailing: LSIconButton(icon: Icons.arrow_forward_ios),
onTap: () async => _defaultSorting(context),
@@ -20,8 +20,8 @@ class SettingsCustomizationSonarrDefaultSortingSeriesTile extends StatelessWidge
if(_values[0]) {
SonarrDatabaseValue.DEFAULT_SORTING_SERIES.put(SonarrSeriesSorting.values[_values[1]]);
// Reset the state of the sorting
context.read<SonarrState>().seriesSortType = SonarrSeriesSorting.values[_values[1]];
context.read<SonarrState>().seriesSortAscending = true;
context.read<SonarrState>().seriesSortType = SonarrDatabaseValue.DEFAULT_SORTING_SERIES.data;
context.read<SonarrState>().seriesSortAscending = SonarrDatabaseValue.DEFAULT_SORTING_SERIES_ASCENDING.data;
}
}
}

View File

@@ -0,0 +1,26 @@
import 'package:flutter/material.dart';
import 'package:lunasea/core.dart';
import 'package:lunasea/modules/sonarr.dart';
class SettingsCustomizationSonarrDefaultSortingSeriesAscendingTile extends StatelessWidget {
@override
Widget build(BuildContext context) => ValueListenableBuilder(
valueListenable: Database.lunaSeaBox.listenable(keys: [SonarrDatabaseValue.DEFAULT_SORTING_SERIES_ASCENDING.key]),
builder: (context, box, _) => LSCardTile(
title: LSTitle(text: 'Series Sort Direction'),
subtitle: LSSubtitle(text: SonarrDatabaseValue.DEFAULT_SORTING_SERIES_ASCENDING.data
? 'Ascending'
: 'Descending'
),
trailing: Switch(
value: SonarrDatabaseValue.DEFAULT_SORTING_SERIES_ASCENDING.data,
onChanged: (value) {
SonarrDatabaseValue.DEFAULT_SORTING_SERIES_ASCENDING.put(value);
// Reset the state of the sorting
context.read<SonarrState>().seriesSortType = SonarrDatabaseValue.DEFAULT_SORTING_SERIES.data;
context.read<SonarrState>().seriesSortAscending = SonarrDatabaseValue.DEFAULT_SORTING_SERIES_ASCENDING.data;
},
),
),
);
}

View File

@@ -19,6 +19,11 @@ class SettingsModulesNZBGetPasswordTile extends StatelessWidget {
context,
'NZBGet Password',
prefill: Database.currentProfileObject.nzbgetPass ?? '',
extraText: [
LSDialog.textSpanContent(text: '${Constants.TEXT_BULLET}\tIf your password includes special characters, considering adding a '),
LSDialog.bolded(text: 'basic authentication'),
LSDialog.textSpanContent(text: ' header with your username and password instead for better support'),
],
);
if(_values[0]) {
Database.currentProfileObject.nzbgetPass = _values[1];

View File

@@ -28,6 +28,8 @@ enum SonarrDatabaseValue {
ADD_SERIES_DEFAULT_ROOT_FOLDER,
DEFAULT_SORTING_SERIES,
DEFAULT_SORTING_RELEASES,
DEFAULT_SORTING_SERIES_ASCENDING,
DEFAULT_SORTING_RELEASES_ASCENDING,
UPCOMING_FUTURE_DAYS,
QUEUE_REFRESH_RATE,
CONTENT_LOAD_LENGTH,
@@ -50,6 +52,8 @@ extension SonarrDatabaseValueExtension on SonarrDatabaseValue {
case SonarrDatabaseValue.ADD_SERIES_DEFAULT_ROOT_FOLDER: return 'SONARR_ADD_SERIES_DEFAULT_ROOT_FOLDER';
case SonarrDatabaseValue.DEFAULT_SORTING_SERIES: return 'SONARR_DEFAULT_SORTING_SERIES';
case SonarrDatabaseValue.DEFAULT_SORTING_RELEASES: return 'SONARR_DEFAULT_SORTING_RELEASES';
case SonarrDatabaseValue.DEFAULT_SORTING_SERIES_ASCENDING: return 'SONARR_DEFAULT_SORTING_SERIES_ASCENDING';
case SonarrDatabaseValue.DEFAULT_SORTING_RELEASES_ASCENDING: return 'SONARR_DEFAULT_SORTING_RELEASES_ASCENDING';
}
throw Exception('key not found');
}
@@ -71,6 +75,8 @@ extension SonarrDatabaseValueExtension on SonarrDatabaseValue {
case SonarrDatabaseValue.ADD_SERIES_DEFAULT_ROOT_FOLDER : return _box.get(this.key, defaultValue: null);
case SonarrDatabaseValue.DEFAULT_SORTING_SERIES: return _box.get(this.key, defaultValue: SonarrSeriesSorting.ALPHABETICAL);
case SonarrDatabaseValue.DEFAULT_SORTING_RELEASES: return _box.get(this.key, defaultValue: SonarrReleasesSorting.WEIGHT);
case SonarrDatabaseValue.DEFAULT_SORTING_SERIES_ASCENDING: return _box.get(this.key, defaultValue: true);
case SonarrDatabaseValue.DEFAULT_SORTING_RELEASES_ASCENDING: return _box.get(this.key, defaultValue: true);
}
throw Exception('data not found');
}

View File

@@ -557,6 +557,48 @@ class SonarrDialogs {
return [_flag];
}
static Future<List<dynamic>> confirmDeleteQueue(BuildContext context) async {
bool _flag = false;
void _setValues(bool flag) {
_flag = flag;
Navigator.of(context, rootNavigator: true).pop();
}
await LSDialog.dialog(
context: context,
title: 'Remove From Queue',
buttons: [
LSDialog.button(
text: 'Remove',
textColor: LunaColours.red,
onPressed: () => _setValues(true),
),
],
content: [
LSDialog.textContent(text: 'Are you sure you want to remove this from the queue?\n'),
Selector<SonarrState, bool>(
selector: (_, state) => state.removeQueueBlacklist,
builder: (context, value, text) => CheckboxListTile(
title: text,
value: value,
onChanged: (selected) => Provider.of<SonarrState>(context, listen: false).removeQueueBlacklist = selected,
contentPadding: LSDialog.tileContentPadding(),
),
child: Text(
'Blacklist',
style: TextStyle(
fontSize: LSDialog.BODY_SIZE,
color: Colors.white,
),
),
),
],
contentPadding: LSDialog.textDialogContentPadding(),
);
return [_flag];
}
static Future<List<dynamic>> confirmDeleteEpisodeFile(BuildContext context) async {
bool _flag = false;

View File

@@ -1,6 +1,7 @@
export 'extensions/sonarr_calendar.dart';
export 'extensions/sonarr_episode.dart';
export 'extensions/sonarr_history_event_type.dart';
export 'extensions/sonarr_queue_record.dart';
export 'extensions/sonarr_series_lookup.dart';
export 'extensions/sonarr_series_season.dart';
export 'extensions/sonarr_series.dart';

View File

@@ -0,0 +1,33 @@
import 'package:flutter/material.dart';
import 'package:lunasea/core.dart';
import 'package:lunasea/modules/sonarr.dart';
extension SonarrQueueRecordExtension on SonarrQueueRecord {
String get lunaStatusText {
switch(this?.status?.toLowerCase() ?? '') {
case 'delay': return 'Pending';
case 'downloading': return 'Downloading';
case 'completed': return 'Completed';
case 'paused': return 'Paused';
}
return this?.status ?? 'Unknown';
}
IconData get lunaStatusIcon {
switch(this?.status?.toLowerCase() ?? '') {
case 'delay': return Icons.schedule;
case 'downloading': return Icons.cloud_download;
case 'completed': return Icons.cloud_download;
case 'paused': return Icons.pause;
}
return Icons.help;
}
Color get lunaStatusColor {
if(this?.status?.toLowerCase() == 'completed') switch(this?.trackedDownloadStatus?.toLowerCase()) {
case 'warning': return LunaColours.orange;
case 'ok': return LunaColours.purple;
}
return Colors.white;
}
}

View File

@@ -1,3 +1,5 @@
import 'dart:async';
import 'package:lunasea/core.dart';
import 'package:lunasea/modules/sonarr.dart';
@@ -5,10 +7,17 @@ class SonarrState extends LunaGlobalState {
SonarrState() {
reset();
}
@override
void dispose() {
_getQueueTimer?.cancel();
super.dispose();
}
@override
void reset() {
// Reset stored data
_queue = null;
_series = null;
_missing = null;
_upcoming = null;
@@ -23,6 +32,7 @@ class SonarrState extends LunaGlobalState {
_releasesSearchQuery = '';
// Reinitialize
resetProfile();
resetQueue();
resetSeries();
resetUpcoming();
resetMissing();
@@ -78,6 +88,45 @@ class SonarrState extends LunaGlobalState {
)
: null;
}
/////////////
/// QUEUE ///
/////////////
/// Timer to handle refreshing queue data
Timer _getQueueTimer;
/// Cancel the periodic timer
void createQueueTimer() => _getQueueTimer = Timer.periodic(
Duration(seconds: SonarrDatabaseValue.QUEUE_REFRESH_RATE.data),
(_) => queue = _api.queue.getQueue(),
);
/// Cancel the queue timer
void cancelQueueTimer() => _getQueueTimer?.cancel();
/// Storing queue data
Future<List<SonarrQueueRecord>> _queue;
Future<List<SonarrQueueRecord>> get queue => _queue;
set queue(Future<List<SonarrQueueRecord>> queue) {
assert(queue != null);
_queue = queue;
notifyListeners();
}
/// Reset the queue:
/// - Cancel timer & clear state of future
/// - Recreate timer (if enabled)
/// - Set initial state of the future
void resetQueue() {
cancelQueueTimer();
_queue = null;
if(_api != null) {
_queue = _api.queue.getQueue();
createQueueTimer();
}
notifyListeners();
}
////////////////
/// EPISODES ///
@@ -173,7 +222,7 @@ class SonarrState extends LunaGlobalState {
notifyListeners();
}
bool _releasesSortAscending = true;
bool _releasesSortAscending = SonarrDatabaseValue.DEFAULT_SORTING_SERIES_ASCENDING.data;
bool get releasesSortAscending => _releasesSortAscending;
set releasesSortAscending(bool releasesSortAscending) {
assert(releasesSortAscending != null);
@@ -209,7 +258,7 @@ class SonarrState extends LunaGlobalState {
notifyListeners();
}
bool _seriesSortAscending = true;
bool _seriesSortAscending = SonarrDatabaseValue.DEFAULT_SORTING_SERIES_ASCENDING.data;
bool get seriesSortAscending => _seriesSortAscending;
set seriesSortAscending(bool seriesSortAscending) {
assert(seriesSortAscending != null);
@@ -356,6 +405,18 @@ class SonarrState extends LunaGlobalState {
notifyListeners();
}
////////////////////
/// DELETE QUEUE ///
////////////////////
bool _removeQueueBlacklist = false;
bool get removeQueueBlacklist => _removeQueueBlacklist;
set removeQueueBlacklist(bool removeQueueBlacklist) {
assert(removeQueueBlacklist != null);
_removeQueueBlacklist = removeQueueBlacklist;
notifyListeners();
}
//////////////
/// IMAGES ///
//////////////

View File

@@ -35,6 +35,7 @@ extension SonarrMonitorStatusExtension on SonarrMonitorStatus {
}
void process(List<SonarrSeriesSeason> season) {
if(season == null || season.length == 0) return;
switch(this) {
case SonarrMonitorStatus.ALL: _all(season); break;
case SonarrMonitorStatus.MISSING: _missing(season); break;

View File

@@ -1,6 +1,8 @@
import 'package:fluro/fluro.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:lunasea/core.dart';
import 'package:lunasea/modules/sonarr.dart';
class SonarrQueueRouter {
static const String ROUTE_NAME = '/sonarr/queue/list';
@@ -28,12 +30,24 @@ class _SonarrQueueRoute extends StatefulWidget {
class _State extends State<_SonarrQueueRoute> {
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
final GlobalKey<RefreshIndicatorState> _refreshKey = GlobalKey<RefreshIndicatorState>();
@override
void initState() {
super.initState();
SchedulerBinding.instance.scheduleFrameCallback((_) => _refresh());
}
Future<void> _refresh() async {
context.read<SonarrState>().resetQueue();
await context.read<SonarrState>().queue;
}
@override
Widget build(BuildContext context) => Scaffold(
key: _scaffoldKey,
appBar: _appBar,
body: LSGenericMessage(text: 'Coming Soon!'),
body: _body,
);
Widget get _appBar => LunaAppBar(
@@ -41,4 +55,48 @@ class _State extends State<_SonarrQueueRoute> {
title: 'Queue',
popUntil: '/sonarr',
);
Widget get _body => LSRefreshIndicator(
refreshKey: _refreshKey,
onRefresh: _refresh,
child: FutureBuilder(
future: context.watch<SonarrState>().queue,
builder: (context, AsyncSnapshot<List<SonarrQueueRecord>> snapshot) {
if(snapshot.hasError) {
if(snapshot.connectionState != ConnectionState.waiting) {
LunaLogger.error(
'_SonarrQueueRoute',
'_body',
'Unable to fetch Sonarr queue',
snapshot.error,
null,
uploadToSentry: !(snapshot.error is DioError),
);
}
return LSErrorMessage(onTapHandler: () async => _refreshKey.currentState.show());
}
if(snapshot.hasData) return snapshot.data.length == 0
? _emptyQueue
: _queue(snapshot.data);
return LSLoader();
},
),
);
Widget get _emptyQueue => LSGenericMessage(
text: 'Empty Queue',
buttonText: 'Refresh',
showButton: true,
onTapHandler: () async => _refreshKey.currentState.show(),
);
Widget _queue(List<SonarrQueueRecord> queue) => LSListView(
children: List.generate(
queue.length,
(index) => SonarrQueueQueueTile(
key: ObjectKey(queue[index].id),
record: queue[index],
),
),
);
}

View File

@@ -0,0 +1 @@
export 'widgets/queue_tile.dart';

View File

@@ -0,0 +1,195 @@
import 'package:flutter/material.dart';
import 'package:expandable/expandable.dart';
import 'package:intl/intl.dart';
import 'package:lunasea/core.dart';
import 'package:lunasea/modules/sonarr.dart';
class SonarrQueueQueueTile extends StatelessWidget {
final SonarrQueueRecord record;
SonarrQueueQueueTile({
Key key,
@required this.record,
}) : super(key: key);
final ExpandableController _controller = ExpandableController();
@override
Widget build(BuildContext context) => LSExpandable(
controller: _controller,
collapsed: _collapsed(context),
expanded: _expanded(context),
);
Widget _collapsed(BuildContext context) => LSCardTile(
title: LSTitle(text: record.title),
subtitle: RichText(
text: TextSpan(
style: TextStyle(
fontSize: Constants.UI_FONT_SIZE_SUBTITLE,
color: Colors.white70,
),
children: [
TextSpan(text: record.series.title),
TextSpan(text: '\nSeason ${record.episode.seasonNumber} ${Constants.TEXT_EMDASH} Episode ${record.episode.episodeNumber}\n'),
TextSpan(
text: record?.quality?.quality?.name ?? 'Unknown',
style: TextStyle(
fontWeight: FontWeight.w600,
color: LunaColours.accent,
),
),
],
),
maxLines: 3,
overflow: TextOverflow.fade,
softWrap: false,
),
trailing: Padding(
child: LSIconButton(icon: record.lunaStatusIcon, color: record.lunaStatusColor),
padding: EdgeInsets.only(bottom: 14.0),
),
padContent: true,
onTap: () => _controller.toggle(),
);
Widget _expanded(BuildContext context) => LSCard(
child: InkWell(
child: Row(
children: [
Expanded(
child: Padding(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LSTitle(text: record.title, softWrap: true, maxLines: 12),
Padding(
child: Wrap(
direction: Axis.horizontal,
runSpacing: 10.0,
children: [
LSTextHighlighted(
text: record.protocol.lsLanguage_Capitalize(),
bgColor: record.protocol == 'torrent'
? LunaColours.purple
: LunaColours.blue,
),
LSTextHighlighted(
text: record?.quality?.quality?.name ?? 'Unknown',
bgColor: LunaColours.accent,
),
LSTextHighlighted(
text: record.lunaStatusText,
bgColor: LunaColours.blueGrey,
),
if(record.trackedDownloadStatus != null && record.trackedDownloadStatus.isNotEmpty) LSTextHighlighted(
text: record.trackedDownloadStatus,
bgColor: LunaColours.blueGrey,
),
],
),
padding: EdgeInsets.only(top: 8.0, bottom: 2.0),
),
Padding(
child: RichText(
text: TextSpan(
style: TextStyle(
color: Colors.white70,
fontSize: Constants.UI_FONT_SIZE_SUBTITLE,
),
children: [
TextSpan(
text: record.episode.seasonNumber == 0
? 'Specials ${Constants.TEXT_EMDASH} Episode ${record.episode.episodeNumber}\n'
: 'Season ${record.episode.seasonNumber} ${Constants.TEXT_EMDASH} Episode ${record.episode.episodeNumber}\n',
style: TextStyle(
color: LunaColours.accent,
fontWeight: FontWeight.w600,
fontSize: Constants.UI_FONT_SIZE_STICKYHEADER,
),
),
TextSpan(
text: record.episode.airDateUtc == null
? 'Unknown Date'
: DateFormat.yMMMMd().format(record.episode.airDateUtc.toLocal()),
style: TextStyle(
color: Colors.white,
),
),
TextSpan(text: '\n\n'),
TextSpan(
text: record.episode.overview == null || record.episode.overview.isEmpty
? 'No overview is available.'
: record.episode.overview,
style: TextStyle(
fontStyle: FontStyle.italic,
),
)
],
),
),
padding: EdgeInsets.only(top: 6.0, bottom: 10.0),
),
Padding(
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
if(record?.statusMessages != null && (record?.statusMessages?.isNotEmpty ?? false)) Expanded(
child: LSButtonSlim(
text: 'Warnings',
backgroundColor: LunaColours.orange,
onTap: () async => LunaDialogs.textPreview(context, 'Warnings', record.statusMessages.fold('', (warnings, status) {
warnings += status.messages.fold<String>('', (message, element) => message += '\n${Constants.TEXT_BULLET} $element');
return warnings.trim();
})),
margin: EdgeInsets.only(right: 6.0),
),
),
Expanded(
child: LSButtonSlim(
text: 'Delete',
backgroundColor: LunaColours.red,
onTap: () async => _deleteQueueRecord(context),
margin: record?.statusMessages != null && (record?.statusMessages?.isNotEmpty ?? false)
? EdgeInsets.only(left: 6.0)
: EdgeInsets.zero,
),
),
],
),
padding: EdgeInsets.only(bottom: 2.0),
),
],
),
padding: EdgeInsets.symmetric(horizontal: 12.0, vertical: 10.0),
),
)
],
),
borderRadius: BorderRadius.circular(Constants.UI_BORDER_RADIUS),
onTap: () => _controller.toggle(),
),
);
Future<void> _deleteQueueRecord(BuildContext context) async {
List _values = await SonarrDialogs.confirmDeleteQueue(context);
if(_values[0]) context.read<SonarrState>().api.queue.deleteQueue(
id: record.id,
blacklist: context.read<SonarrState>().removeQueueBlacklist,
).then((value) {
context.read<SonarrState>().resetQueue();
showLunaSuccessSnackBar(context: context, title: 'Removed From Queue', message: record.title);
})
.catchError((error, stack) {
LunaLogger.error(
'SonarrQueueQueueTile',
'_deleteQueueRecord',
'Failed to remove item from queue: ${record.id}',
error,
stack,
uploadToSentry: !(error is DioError),
);
showLunaErrorSnackBar(context: context, title: 'Failed to Delete From Queue');
});
}
}

View File

@@ -77,8 +77,8 @@ class _State extends State<SonarrSeriesSeasonDetailsEpisodeTile> {
children: [
TextSpan(
text: widget.episode.seasonNumber == 0
? 'Specials / Episode ${widget.episode.episodeNumber}\n'
: 'Season ${widget.episode.seasonNumber} / Episode ${widget.episode.episodeNumber}\n',
? 'Specials ${Constants.TEXT_EMDASH} Episode ${widget.episode.episodeNumber}\n'
: 'Season ${widget.episode.seasonNumber} ${Constants.TEXT_EMDASH} Episode ${widget.episode.episodeNumber}\n',
style: TextStyle(
color: LunaColours.accent,
fontWeight: FontWeight.w600,

View File

@@ -24,13 +24,7 @@ class SonarrAppBarGlobalSettingsAction extends StatelessWidget {
Future<void> _webGUI(BuildContext context) async => Provider.of<SonarrState>(context, listen: false).host.lsLinks_OpenLink();
Future<void> _viewQueue(BuildContext context) async => LSSnackBar(
context: context,
title: 'Coming Soon!',
message: 'This feature has not yet been implemented',
type: SNACKBAR_TYPE.info,
);
//Future<void> _viewQueue(BuildContext context) async => SonarrQueueRouter.navigateTo(context);
Future<void> _viewQueue(BuildContext context) async => SonarrQueueRouter.navigateTo(context);
Future<void> _manageTags(BuildContext context) async => SonarrTagsRouter.navigateTo(context);

View File

@@ -56,14 +56,14 @@ packages:
name: build
url: "https://pub.dartlang.org"
source: hosted
version: "1.5.0"
version: "1.5.1"
build_config:
dependency: transitive
description:
name: build_config
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.2"
version: "0.4.3"
build_daemon:
dependency: transitive
description:
@@ -84,14 +84,14 @@ packages:
name: build_runner
url: "https://pub.dartlang.org"
source: hosted
version: "1.10.4"
version: "1.10.6"
build_runner_core:
dependency: transitive
description:
name: build_runner_core
url: "https://pub.dartlang.org"
source: hosted
version: "6.0.3"
version: "6.1.1"
built_collection:
dependency: transitive
description:
@@ -182,7 +182,7 @@ packages:
name: dart_style
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.9"
version: "1.3.10"
dartx:
dependency: transitive
description:
@@ -294,7 +294,7 @@ packages:
name: fluro
url: "https://pub.dartlang.org"
source: hosted
version: "1.7.7"
version: "1.7.8"
flutter:
dependency: "direct main"
description: flutter
@@ -458,7 +458,7 @@ packages:
name: json_annotation
url: "https://pub.dartlang.org"
source: hosted
version: "3.1.0"
version: "3.1.1"
logging:
dependency: transitive
description:
@@ -500,14 +500,14 @@ packages:
name: node_interop
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
version: "1.2.1"
node_io:
dependency: transitive
description:
name: node_io
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.1"
version: "1.2.0"
package_config:
dependency: transitive
description:
@@ -736,7 +736,7 @@ packages:
name: sonarr
url: "https://pub.dartlang.org"
source: hosted
version: "0.0.2-pre.3"
version: "0.0.4"
source_gen:
dependency: transitive
description:
@@ -792,7 +792,7 @@ packages:
name: table_calendar
url: "https://pub.dartlang.org"
source: hosted
version: "2.3.0"
version: "2.3.1"
tautulli:
dependency: "direct main"
description:
@@ -813,7 +813,7 @@ packages:
name: time
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.0"
version: "1.4.0"
timing:
dependency: transitive
description:

View File

@@ -1,6 +1,6 @@
name: lunasea
description: Self Hosted Manager
version: 4.1.0+40100004
version: 4.1.0+40100005
publish_to: 'none'
environment:
sdk: ">=2.7.0 <3.0.0"
@@ -14,7 +14,7 @@ dependencies:
file_picker: ^1.13.3
flare_flutter: ^2.0.6
flash: ^1.3.1
fluro: ^1.7.7
fluro: ^1.7.8
flutter:
sdk: flutter
flutter_spinkit: ^4.1.2+1
@@ -35,13 +35,13 @@ dependencies:
quick_actions: ^0.4.0+10
sentry: ^3.0.1
stack_trace: ^1.9.6
table_calendar: ^2.3.0
table_calendar: ^2.3.1
tuple: ^1.0.3
url_launcher: ^5.7.10
uuid: ^2.2.2
xml_parser: ^0.1.2
# Comet.Tools Packages
sonarr: ^0.0.2-pre.3
sonarr: ^0.0.4
tautulli: ^1.1.0
wake_on_lan: ^1.1.1+2