Flutter Music Application
Alif Adrian Anzary - 5025201274
Pada tugas kali ini akan mencoba membuat sebuah aplikasi musik menggunakan framework Flutter. Aplikasi ini nantinya dapat memutar musik, melihat daftar lagu, melihat artist dan lagu-lagunya, dan masih banyak lagi. Aplikasi ini dibuat dengan mengikuti panduan dari Codelabs dengan melewati beberapa step. Berikut adalah implementasi kode yang saya gunakan:
extensions.dart
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
// Add Google Fonts Package import
extension TypographyUtils on BuildContext {
ThemeData get theme => Theme.of(this);
TextTheme get textTheme =>
GoogleFonts.montserratTextTheme(theme.textTheme); // Modify this line
ColorScheme get colors => theme.colorScheme;
TextStyle? get displayLarge => textTheme.displayLarge?.copyWith(
color: colors.onSurface,
);
TextStyle? get displayMedium => textTheme.displayMedium?.copyWith(
color: colors.onSurface,
);
TextStyle? get displaySmall => textTheme.displaySmall?.copyWith(
color: colors.onSurface,
);
TextStyle? get headlineLarge => textTheme.headlineLarge?.copyWith(
color: colors.onSurface,
);
TextStyle? get headlineMedium => textTheme.headlineMedium?.copyWith(
color: colors.onSurface,
);
TextStyle? get headlineSmall => textTheme.headlineSmall?.copyWith(
color: colors.onSurface,
);
TextStyle? get titleLarge => textTheme.titleLarge?.copyWith(
color: colors.onSurface,
);
TextStyle? get titleMedium => textTheme.titleMedium?.copyWith(
color: colors.onSurface,
);
TextStyle? get titleSmall => textTheme.titleSmall?.copyWith(
color: colors.onSurface,
);
TextStyle? get labelLarge => textTheme.labelLarge?.copyWith(
color: colors.onSurface,
);
TextStyle? get labelMedium => textTheme.labelMedium?.copyWith(
color: colors.onSurface,
);
TextStyle? get labelSmall => textTheme.labelSmall?.copyWith(
color: colors.onSurface,
);
TextStyle? get bodyLarge => textTheme.bodyLarge?.copyWith(
color: colors.onSurface,
);
TextStyle? get bodyMedium => textTheme.bodyMedium?.copyWith(
color: colors.onSurface,
);
TextStyle? get bodySmall => textTheme.bodySmall?.copyWith(
color: colors.onSurface,
);
}
extension BreakpointUtils on BoxConstraints {
bool get isTablet => maxWidth > 730;
bool get isDesktop => maxWidth > 1200;
bool get isMobile => !isTablet && !isDesktop;
}
extension DurationString on String {
/// Assumes a string (roughly) of the format '\d{1,2}:\d{2}'
Duration toDuration() => switch (split(':')) {
[var minutes, var seconds] => Duration(
minutes: int.parse(minutes.trim()),
seconds: int.parse(seconds.trim()),
),
[var hours, var minutes, var seconds] => Duration(
hours: int.parse(hours.trim()),
minutes: int.parse(minutes.trim()),
seconds: int.parse(seconds.trim()),
),
_ => throw Exception('Invalid duration string: $this'),
};
}
extension HumanizedDuration on Duration {
String toHumanizedString() {
final seconds = '${inSeconds % 60}'.padLeft(2, '0');
String minutes = '${inMinutes % 60}';
if (inHours > 0 || inMinutes == 0) {
minutes = minutes.padLeft(2, '0');
}
String value = '$minutes:$seconds';
if (inHours > 0) {
value = '$inHours:$minutes:$seconds';
}
return value;
}
}
router.dart
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
// Add Google Fonts Package import
extension TypographyUtils on BuildContext {
ThemeData get theme => Theme.of(this);
TextTheme get textTheme =>
GoogleFonts.montserratTextTheme(theme.textTheme); // Modify this line
ColorScheme get colors => theme.colorScheme;
TextStyle? get displayLarge => textTheme.displayLarge?.copyWith(
color: colors.onSurface,
);
TextStyle? get displayMedium => textTheme.displayMedium?.copyWith(
color: colors.onSurface,
);
TextStyle? get displaySmall => textTheme.displaySmall?.copyWith(
color: colors.onSurface,
);
TextStyle? get headlineLarge => textTheme.headlineLarge?.copyWith(
color: colors.onSurface,
);
TextStyle? get headlineMedium => textTheme.headlineMedium?.copyWith(
color: colors.onSurface,
);
TextStyle? get headlineSmall => textTheme.headlineSmall?.copyWith(
color: colors.onSurface,
);
TextStyle? get titleLarge => textTheme.titleLarge?.copyWith(
color: colors.onSurface,
);
TextStyle? get titleMedium => textTheme.titleMedium?.copyWith(
color: colors.onSurface,
);
TextStyle? get titleSmall => textTheme.titleSmall?.copyWith(
color: colors.onSurface,
);
TextStyle? get labelLarge => textTheme.labelLarge?.copyWith(
color: colors.onSurface,
);
TextStyle? get labelMedium => textTheme.labelMedium?.copyWith(
color: colors.onSurface,
);
TextStyle? get labelSmall => textTheme.labelSmall?.copyWith(
color: colors.onSurface,
);
TextStyle? get bodyLarge => textTheme.bodyLarge?.copyWith(
color: colors.onSurface,
);
TextStyle? get bodyMedium => textTheme.bodyMedium?.copyWith(
color: colors.onSurface,
);
TextStyle? get bodySmall => textTheme.bodySmall?.copyWith(
color: colors.onSurface,
);
}
extension BreakpointUtils on BoxConstraints {
bool get isTablet => maxWidth > 730;
bool get isDesktop => maxWidth > 1200;
bool get isMobile => !isTablet && !isDesktop;
}
extension DurationString on String {
/// Assumes a string (roughly) of the format '\d{1,2}:\d{2}'
Duration toDuration() => switch (split(':')) {
[var minutes, var seconds] => Duration(
minutes: int.parse(minutes.trim()),
seconds: int.parse(seconds.trim()),
),
[var hours, var minutes, var seconds] => Duration(
hours: int.parse(hours.trim()),
minutes: int.parse(minutes.trim()),
seconds: int.parse(seconds.trim()),
),
_ => throw Exception('Invalid duration string: $this'),
};
}
extension HumanizedDuration on Duration {
String toHumanizedString() {
final seconds = '${inSeconds % 60}'.padLeft(2, '0');
String minutes = '${inMinutes % 60}';
if (inHours > 0 || inMinutes == 0) {
minutes = minutes.padLeft(2, '0');
}
String value = '$minutes:$seconds';
if (inHours > 0) {
value = '$inHours:$minutes:$seconds';
}
return value;
}
}
view rawextensions.dart hosted with ❤ by GitHub
// Copyright 2022 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import '../features/artists/artists.dart';
import '../features/home/home.dart';
import '../features/playlists/playlists.dart';
import '../features/playlists/view/view.dart';
import 'providers/artists.dart';
import 'providers/playlists.dart';
import 'views/views.dart';
const _pageKey = ValueKey('_pageKey');
const _scaffoldKey = ValueKey('_scaffoldKey');
final artistsProvider = ArtistsProvider();
final playlistsProvider = PlaylistsProvider();
const List<NavigationDestination> destinations = [
NavigationDestination(
label: 'Home',
icon: Icon(Icons.home), // Modify this line
route: '/',
),
NavigationDestination(
label: 'Playlists',
icon: Icon(Icons.playlist_add_check), // Modify this line
route: '/playlists',
),
NavigationDestination(
label: 'Artists',
icon: Icon(Icons.people), // Modify this line
route: '/artists',
),
];
class NavigationDestination {
const NavigationDestination({
required this.route,
required this.label,
required this.icon,
this.child,
});
final String route;
final String label;
final Icon icon;
final Widget? child;
}
final appRouter = GoRouter(
routes: [
// HomeScreen
GoRoute(
path: '/',
pageBuilder: (context, state) => const MaterialPage<void>(
key: _pageKey,
child: RootLayout(
key: _scaffoldKey,
currentIndex: 0,
child: HomeScreen(),
),
),
),
// PlaylistHomeScreen
GoRoute(
path: '/playlists',
pageBuilder: (context, state) => const MaterialPage<void>(
key: _pageKey,
child: RootLayout(
key: _scaffoldKey,
currentIndex: 1,
child: PlaylistHomeScreen(),
),
),
routes: [
GoRoute(
path: ':pid',
pageBuilder: (context, state) => MaterialPage<void>(
key: state.pageKey,
child: RootLayout(
key: _scaffoldKey,
currentIndex: 1,
child: PlaylistScreen(
playlist: playlistsProvider
.getPlaylist(state.pathParameters['pid']!)!,
),
),
),
),
],
),
// ArtistHomeScreen
GoRoute(
path: '/artists',
pageBuilder: (context, state) => const MaterialPage<void>(
key: _pageKey,
child: RootLayout(
key: _scaffoldKey,
currentIndex: 2,
child: ArtistsScreen(),
),
),
routes: [
GoRoute(
path: ':aid',
pageBuilder: (context, state) => MaterialPage<void>(
key: state.pageKey,
child: RootLayout(
key: _scaffoldKey,
currentIndex: 2,
child: ArtistScreen(
artist:
artistsProvider.getArtist(state.pathParameters['aid']!)!,
),
),
),
// builder: (context, state) => ArtistScreen(
// id: state.params['aid']!,
// ),
),
],
),
for (final route in destinations.skip(3))
GoRoute(
path: route.route,
pageBuilder: (context, state) => MaterialPage<void>(
key: _pageKey,
child: RootLayout(
key: _scaffoldKey,
currentIndex: destinations.indexOf(route),
child: const SizedBox(),
),
),
),
],
);
Comments
Post a Comment