Files
lunasea/lib/core/extensions/string.dart
Jagandeep Brar 57404f2dc2 [Release] v5.0.0 (50000013) (#376)
NEW
- [-Arr/Releases] Match torrent seeder colours to the web GUI
- [Firebase/Analytics] Added analytics for breadcrumb tracking in crashes
- [Logger] Utilize a new, custom built on-device logging system
- [Logger] Compact/delete old log entries once the log count passes 100
- [Logger] Exported logs are now in JSON format
- [Routing] Protect all module routes by showing a "Not Enabled" screen when the module is not enabled
- [Settings/System] Added toggle to disable Firebase Analytics
- [Tautulli/Activity] Show custom season titles from Plex's new TV agent

TWEAKS
- [Radarr/Files] Add languages to file block
- [Radarr/Files] Small changes to table titles
- [System/Logs] Reimplemented logger view
- [System/Logs] Removed viewing the stack trace within the application (still viewable within the exported logs)
- [System/Logs] Added the exception to the expanded table instead of a separate dialog popup
- [Tautulli/Activity] Minor UI tweaks including showing the full season title and italicizing the episode title
- [UI/Navbar] Jump instead of animate to page when tapping a navbar item

FIXES
- [Firebase/Crashes] Do not log DioError/networking exceptions
- [Flutter] Updated packages
- [Flutter] Upgrade all Comet.Tools packages to null-safety/NNBD
- [Radarr/Releases] Negative format scores were not being shown
- [Share] The sharesheet could break after the first time it was opened
- [Strings] Safe-guard many substring operations
- [Tautulli/Activity] Play/paused/buffering icon was not properly left aligned to the text
- [Tautulli/Users] User images would not be fetched on newer versions of Tautulli
- [UI/UX] Modal scroll controller was not being attached to the ListView in a bottom modal sheet
- [UI/UX] Do not log errors when network images fail to load
- [UI/UX] Prevent attempting to load background images that are passed an empty URL
- [URLs] Safe-guard launching specific invalid URLs
2021-03-17 19:51:28 -05:00

81 lines
4.1 KiB
Dart

import 'package:lunasea/core.dart';
import 'package:url_launcher/url_launcher.dart';
extension StringExtension on String {
/// Returns a string with all first letters of each word capitalized
///
/// Default word splitting pattern is by a space.
String lunaCapitalizeFirstLetters({ Pattern pattern = ' ' }) {
List<String> split = this.split(pattern);
for(var i=0; i<split.length; i++) {
if(split[i].length == 1) {
split[i] = split[i].toUpperCase();
} else {
split[i] = split[i].substring(0, 1).toUpperCase()+split[i].substring(1);
}
}
return split.join(pattern);
}
/// Convert a string into a slug format.
///
/// Example "LunaSea Flutter" => 'lunasea-flutter';
String lunaConvertToSlug() => this.toLowerCase().replaceAll(RegExp(r'[\ \.]'), '-').replaceAll(RegExp(r'[^a-zA-Z0-9\-]'), '').trim();
/// Pad a string on both sides with the spacer value [count] amount of times.
/// Count is the amount of times to add the [padding] on each time, and not the maximum total width of the string unlike [padLeft] and [padRight].
///
/// Example "LunaSea" with count 2 and padding "1" would return "11LunaSea11".
String lunaPad([int count = 1, String padding = ' ']) {
String _value = this.padLeft((this.length+count), padding).padRight((this.length+(count*2)), padding);
return _value;
}
}
extension StringLinksExtension on String {
Future<void> _openLink(String url) async {
try {
//Attempt to launch the link forced as a universal link
if(await _launchUniversalLink(url)) return;
//If that fails and we're using a custom browser, format the link for the correct browser and attempt to launch
LunaBrowser _browser = LunaDatabaseValue.SELECTED_BROWSER.data;
if(_browser != LunaBrowser.APPLE_SAFARI && await _launchCustomBrowser(_browser.formatted(url))) return;
//If all else fails, just launch it in Safari/stock browser
await _launch(url);
} catch (error, stack) {
LunaLogger().error('Unable to open link: $url', error, stack);
}
}
Future<bool> _launchUniversalLink(String url) async => await launch(url, forceSafariVC: false, universalLinksOnly: true);
Future<bool> _launchCustomBrowser(String url) async => await launch(url, forceSafariVC: false);
Future<bool> _launch(String url) async => await launch(url);
/// Attempt to open this string as a URL in a browser.
Future<void> lunaOpenGenericLink() async => await _openLink(this);
/// Attach this string as an ID/title to IMDB and attempt to launch it as a URL.
Future<void> lunaOpenIMDB() async => await _openLink('https://www.imdb.com/title/$this');
/// Attach this string as a video ID to YouTube and attempt to launch it as a URL.
Future<void> lunaOpenYouTube() async => await _openLink('https://www.youtube.com/watch?v=$this');
/// Attach this string as a movie ID to TheMovieDB and attempt to launch it as a URL.
Future<void> lunaOpenTheMovieDBMovie() async => await _openLink('https://www.themoviedb.org/movie/$this');
/// Attach this string as a person ID to TheMovieDB and attempt to launch it as a URL.
Future<void> lunaOpenTheMovieDBCredits() async => await _openLink('https://www.themoviedb.org/person/$this');
/// Attach this string as a series ID to TheTVDB and attempt to launch it as a URL.
Future<void> lunaOpenTheTVDB() async => await _openLink('https://www.thetvdb.com/?id=$this&tab=series');
/// Attach this string as a TVDB ID to Trakt and attempt to launch it as a URL.
Future<void> lunaOpenTraktSeries() async => await _openLink('http://trakt.tv/search/tvdb/$this?id_type=show');
/// Attach this string as a TMDB ID to Trakt and attempt to launch it as a URL.
Future<void> lunaOpenTraktMovie() async => await _openLink('https://trakt.tv/search/tmdb/$this?id_type=movie');
/// Attach this string as a series ID to TVMaze and attempt to launch it as a URL.
Future<void> lunaOpenTVMaze() async => await _openLink('https://www.tvmaze.com/shows/$this');
}