responsive web version

This commit is contained in:
MohammadTaha Basiri 2022-05-01 20:11:58 +04:30
parent 41be81e532
commit d9c930c494
6 changed files with 201 additions and 165 deletions

View File

@ -195,7 +195,7 @@ class RouteGenerator {
data: MediaQuery.of(context).copyWith( data: MediaQuery.of(context).copyWith(
textScaleFactor: 1.0, textScaleFactor: 1.0,
size: Size( size: Size(
deviceSize.width / 16 * 9, deviceSize.height * 9 / 16,
deviceSize.height, deviceSize.height,
), ),
), ),

View File

@ -9,21 +9,33 @@ import 'package:didvan/models/view/action_sheet_data.dart';
import 'package:didvan/models/view/alert_data.dart'; import 'package:didvan/models/view/alert_data.dart';
import 'package:didvan/views/widgets/didvan/button.dart'; import 'package:didvan/views/widgets/didvan/button.dart';
import 'package:didvan/views/widgets/didvan/text.dart'; import 'package:didvan/views/widgets/didvan/text.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:rive/rive.dart'; import 'package:rive/rive.dart';
class ActionSheetUtils { class ActionSheetUtils {
static late BuildContext context; static late BuildContext context;
static MediaQueryData get mediaQueryData {
final ds = MediaQuery.of(context).size;
double width = ds.width;
final shortestSide = ds.shortestSide;
final bool useMobileLayout = shortestSide < 600;
if (kIsWeb && !useMobileLayout) {
width = ds.height * 9 / 16;
}
return MediaQuery.of(context).copyWith(size: Size(width, ds.height));
}
static Future<void> showLogoLoadingIndicator() async { static Future<void> showLogoLoadingIndicator() async {
await showDialog( await showDialog(
barrierDismissible: false, barrierDismissible: false,
context: context, context: context,
builder: (context) => Padding( builder: (context) => Center(
padding: EdgeInsets.symmetric( child: SizedBox(
horizontal: MediaQuery.of(context).size.width / 3, width: mediaQueryData.size.width * 0.4,
child: RiveAnimation.asset(Assets.logoLoadingAnimation),
), ),
child: RiveAnimation.asset(Assets.logoLoadingAnimation),
), ),
); );
} }
@ -76,6 +88,9 @@ class ActionSheetUtils {
static Future<void> showBottomSheet({required ActionSheetData data}) async { static Future<void> showBottomSheet({required ActionSheetData data}) async {
await showModalBottomSheet( await showModalBottomSheet(
constraints: BoxConstraints(
maxWidth: mediaQueryData.size.width,
),
backgroundColor: Colors.transparent, backgroundColor: Colors.transparent,
isScrollControlled: true, isScrollControlled: true,
context: context, context: context,
@ -168,7 +183,8 @@ class ActionSheetUtils {
shape: const RoundedRectangleBorder( shape: const RoundedRectangleBorder(
borderRadius: DesignConfig.mediumBorderRadius, borderRadius: DesignConfig.mediumBorderRadius,
), ),
child: Padding( child: Container(
width: mediaQueryData.size.width * 0.8,
padding: const EdgeInsets.all(24.0), padding: const EdgeInsets.all(24.0),
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,

View File

@ -60,10 +60,10 @@ class CategoryItem extends StatelessWidget {
child: Container( child: Container(
width: !_useWebMobileLayout(context) width: !_useWebMobileLayout(context)
? _width(context) / 2 ? _width(context) / 2
: ds.width / 5, : ds.width / 7,
height: !_useWebMobileLayout(context) height: !_useWebMobileLayout(context)
? _width(context) / 2 ? _width(context) / 2
: ds.width / 5, : ds.width / 7,
decoration: BoxDecoration( decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surface, color: Theme.of(context).colorScheme.surface,
boxShadow: DesignConfig.defaultShadow, boxShadow: DesignConfig.defaultShadow,

View File

@ -3,7 +3,9 @@ import 'package:didvan/config/design_config.dart';
import 'package:didvan/config/theme_data.dart'; import 'package:didvan/config/theme_data.dart';
import 'package:didvan/constants/app_icons.dart'; import 'package:didvan/constants/app_icons.dart';
import 'package:didvan/models/enums.dart'; import 'package:didvan/models/enums.dart';
import 'package:didvan/models/view/action_sheet_data.dart';
import 'package:didvan/services/media/media.dart'; import 'package:didvan/services/media/media.dart';
import 'package:didvan/utils/action_sheet.dart';
import 'package:didvan/views/home/studio/studio_details/studio_details_state.dart'; import 'package:didvan/views/home/studio/studio_details/studio_details_state.dart';
import 'package:didvan/views/home/studio/studio_details/widgets/studio_details_widget.dart'; import 'package:didvan/views/home/studio/studio_details/widgets/studio_details_widget.dart';
import 'package:didvan/views/home/studio/studio_state.dart'; import 'package:didvan/views/home/studio/studio_state.dart';
@ -275,70 +277,77 @@ class _PlayerNavBar extends StatelessWidget {
} }
final state = context.read<StudioState>(); final state = context.read<StudioState>();
showModalBottomSheet( showModalBottomSheet(
constraints: BoxConstraints(
maxWidth: ActionSheetUtils.mediaQueryData.size.width,
),
backgroundColor: Colors.transparent, backgroundColor: Colors.transparent,
context: context, context: context,
isScrollControlled: true, isScrollControlled: true,
builder: (context) => ChangeNotifierProvider<StudioState>.value( builder: (context) => ChangeNotifierProvider<StudioState>.value(
value: state, value: state,
child: Consumer<StudioDetailsState>( child: Consumer<StudioDetailsState>(
builder: (context, state, child) => ExpandableBottomSheet( builder: (context, state, child) => MediaQuery(
key: sheetKey, data: ActionSheetUtils.mediaQueryData,
background: Align( child: ExpandableBottomSheet(
alignment: Alignment.bottomCenter, key: sheetKey,
child: Container( background: Align(
height: MediaQuery.of(context).size.height * 0.7, alignment: Alignment.bottomCenter,
color: Theme.of(context).colorScheme.surface, child: Container(
height: MediaQuery.of(context).size.height * 0.7,
color: Theme.of(context).colorScheme.surface,
),
), ),
), persistentHeader: GestureDetector(
persistentHeader: GestureDetector( onVerticalDragUpdate: (details) {
onVerticalDragUpdate: (details) { if (details.delta.dy > 10) {
if (details.delta.dy > 10) { Navigator.of(context).pop();
Navigator.of(context).pop(); }
} },
}, child: Column(
child: Column( crossAxisAlignment: CrossAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center, children: [
children: [ AudioPlayerWidget(
AudioPlayerWidget( podcast: MediaService.currentPodcast!,
podcast: MediaService.currentPodcast!,
),
Container(
width: MediaQuery.of(context).size.width,
color: Theme.of(context).colorScheme.surface,
child: Column(
children: [
DidvanIconButton(
size: 32,
icon: DidvanIcons.angle_up_regular,
onPressed: () {
if (!isExpanded) {
sheetKey.currentState?.expand();
isExpanded = true;
} else {
isExpanded = false;
sheetKey.currentState?.contract();
}
},
),
const SizedBox(height: 16),
],
), ),
), Container(
], width: MediaQuery.of(context).size.width,
color: Theme.of(context).colorScheme.surface,
child: Column(
children: [
DidvanIconButton(
size: 32,
icon: DidvanIcons.angle_up_regular,
onPressed: () {
if (!isExpanded) {
sheetKey.currentState?.expand();
isExpanded = true;
} else {
isExpanded = false;
sheetKey.currentState?.contract();
}
},
),
const SizedBox(height: 16),
],
),
),
],
),
), ),
), expandableContent: state.appState == AppState.busy
expandableContent: state.appState == AppState.busy ? Container(
? Container( height: MediaQuery.of(context).size.height / 2,
height: MediaQuery.of(context).size.height / 2, alignment: Alignment.center,
alignment: Alignment.center, child: SpinKitSpinningLines(
child: SpinKitSpinningLines( color: Theme.of(context).colorScheme.primary,
color: Theme.of(context).colorScheme.primary, ),
)
: StudioDetailsWidget(
onMarkChanged: (id, value) => context
.read<StudioState>()
.changeMark(id, value, true),
), ),
) ),
: StudioDetailsWidget(
onMarkChanged: (id, value) =>
context.read<StudioState>().changeMark(id, value, true),
),
), ),
), ),
), ),

View File

@ -235,31 +235,34 @@ class _DidvanPageViewState extends State<DidvanPageView> {
borderRadius: DesignConfig.lowBorderRadius, borderRadius: DesignConfig.lowBorderRadius,
), ),
alignment: Alignment.center, alignment: Alignment.center,
child: DidvanCard( child: SizedBox(
child: Column( width: ActionSheetUtils.mediaQueryData.size.width,
mainAxisSize: MainAxisSize.min, child: DidvanCard(
children: [ child: Column(
Row( mainAxisSize: MainAxisSize.min,
children: [ children: [
Icon( Row(
DidvanIcons.info_circle_solid, children: [
color: Theme.of(context).colorScheme.primary, Icon(
), DidvanIcons.info_circle_solid,
const SizedBox(width: 8), color: Theme.of(context).colorScheme.primary,
DidvanText( ),
element!.text, const SizedBox(width: 8),
style: Theme.of(context).textTheme.subtitle2, DidvanText(
), element!.text,
], style: Theme.of(context).textTheme.subtitle2,
), ),
const SizedBox(height: 8), ],
DidvanText(href.split('-').last), ),
const SizedBox(height: 16), const SizedBox(height: 8),
const DidvanButton( DidvanText(href.split('-').last),
title: 'بستن', const SizedBox(height: 16),
onPressed: ActionSheetUtils.pop, const DidvanButton(
), title: 'بستن',
], onPressed: ActionSheetUtils.pop,
),
],
),
), ),
), ),
), ),

View File

@ -1,7 +1,7 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<!-- <!--
If you are serving your web app in a path other than the root, change the If you are serving your web app in a path other than the root, change the
href value below to reflect the base path you are serving from. href value below to reflect the base path you are serving from.
@ -14,70 +14,78 @@
This is a placeholder for base href that will be replaced by the value of This is a placeholder for base href that will be replaced by the value of
the `--base-href` argument provided to `flutter build`. the `--base-href` argument provided to `flutter build`.
--> -->
<base href="$FLUTTER_BASE_HREF"> <base href="$FLUTTER_BASE_HREF" />
<meta charset="UTF-8"> <meta charset="UTF-8" />
<meta content="IE=Edge" http-equiv="X-UA-Compatible"> <meta content="IE=Edge" http-equiv="X-UA-Compatible" />
<meta name="description" content="A new Flutter project."> <meta name="description" content="A new Flutter project." />
<!-- iOS meta tags & icons --> <!-- iOS meta tags & icons -->
<meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black"> <meta name="apple-mobile-web-app-status-bar-style" content="black" />
<meta name="apple-mobile-web-app-title" content="didvan"> <meta name="apple-mobile-web-app-title" content="didvan" />
<link rel="apple-touch-icon" href="icons/icon.png"> <link rel="apple-touch-icon" href="icons/icon.png" />
<!-- Favicon --> <!-- Favicon -->
<link rel="icon" type="image/png" href="favicon.png"/> <link rel="icon" type="image/png" href="favicon.png" />
<title>Didvan</title> <title>Didvan</title>
<link rel="manifest" href="manifest.json"> <link rel="manifest" href="manifest.json" />
<style> <style>
.container { .container {
width: 100vw; width: 100vw;
height: 100vh; height: 100vh;
display: flex; /* Default Axis is X*/ display: flex;
justify-content: center; /* Main Axis */ justify-content: center;
align-items: center; /* Cross Axis */ align-items: center;
} }
.indicator{
width: 50vw; .indicator {
} width: 50vw;
</style> }
</head>
<body style="overflow: hidden"> @media only screen and (min-width: 600px) {
<div id="loading_indicator" class="container"> .indicator {
<img class="indicator" src="./assets/lib/assets/animations/loading.gif" /> width: 25vw;
</div> }
<!-- This script installs service_worker.js to provide PWA functionality to }
</style>
</head>
<body style="overflow: hidden">
<div id="loading_indicator" class="container">
<img class="indicator" src="./assets/lib/assets/animations/loading.gif" />
</div>
<!-- This script installs service_worker.js to provide PWA functionality to
application. For more information, see: application. For more information, see:
https://developers.google.com/web/fundamentals/primers/service-workers --> https://developers.google.com/web/fundamentals/primers/service-workers -->
<script> <script>
var serviceWorkerVersion = null; var serviceWorkerVersion = null;
var scriptLoaded = false; var scriptLoaded = false;
function loadMainDartJs() { function loadMainDartJs() {
if (scriptLoaded) { if (scriptLoaded) {
return; return;
}
scriptLoaded = true;
var scriptTag = document.createElement("script");
scriptTag.src = `main.dart.js?version=${Math.random()}`;
scriptTag.type = "application/javascript";
document.body.append(scriptTag);
} }
scriptLoaded = true;
var scriptTag = document.createElement('script');
scriptTag.src = `main.dart.js?version=${Math.random()}`;
scriptTag.type = 'application/javascript';
document.body.append(scriptTag);
}
if ('serviceWorker' in navigator) { if ("serviceWorker" in navigator) {
// Service workers are supported. Use them. // Service workers are supported. Use them.
window.addEventListener('load', function () { window.addEventListener("load", function () {
// Wait for registration to finish before dropping the <script> tag. // Wait for registration to finish before dropping the <script> tag.
// Otherwise, the browser will load the script multiple times, // Otherwise, the browser will load the script multiple times,
// potentially different versions. // potentially different versions.
var serviceWorkerUrl = 'flutter_service_worker.js?v=' + serviceWorkerVersion; var serviceWorkerUrl =
navigator.serviceWorker.register(serviceWorkerUrl) "flutter_service_worker.js?v=" + serviceWorkerVersion;
.then((reg) => { navigator.serviceWorker.register(serviceWorkerUrl).then((reg) => {
function waitForActivation(serviceWorker) { function waitForActivation(serviceWorker) {
serviceWorker.addEventListener('statechange', () => { serviceWorker.addEventListener("statechange", () => {
if (serviceWorker.state == 'activated') { if (serviceWorker.state == "activated") {
console.log('Installed new service worker.'); console.log("Installed new service worker.");
loadMainDartJs(); loadMainDartJs();
} }
}); });
@ -89,39 +97,39 @@
} else if (!reg.active.scriptURL.endsWith(serviceWorkerVersion)) { } else if (!reg.active.scriptURL.endsWith(serviceWorkerVersion)) {
// When the app updates the serviceWorkerVersion changes, so we // When the app updates the serviceWorkerVersion changes, so we
// need to ask the service worker to update. // need to ask the service worker to update.
console.log('New service worker available.'); console.log("New service worker available.");
reg.update(); reg.update();
waitForActivation(reg.installing); waitForActivation(reg.installing);
} else { } else {
// Existing service worker is still good. // Existing service worker is still good.
console.log('Loading app from service worker.'); console.log("Loading app from service worker.");
loadMainDartJs(); loadMainDartJs();
} }
}); });
// If service worker doesn't succeed in a reasonable amount of time, // If service worker doesn't succeed in a reasonable amount of time,
// fallback to plaint <script> tag. // fallback to plaint <script> tag.
setTimeout(() => { setTimeout(() => {
if (!scriptLoaded) { if (!scriptLoaded) {
console.warn( console.warn(
'Failed to load app from service worker. Falling back to plain <script> tag.', "Failed to load app from service worker. Falling back to plain <script> tag."
); );
loadMainDartJs(); loadMainDartJs();
} }
}, 4000); }, 4000);
}); });
} else { } else {
// Service workers not supported. Just drop the <script> tag. // Service workers not supported. Just drop the <script> tag.
loadMainDartJs(); loadMainDartJs();
} }
window.onload = function () { window.onload = function () {
setTimeout(function () { setTimeout(function () {
var loadingIndicator = document.getElementById("loading_indicator"); var loadingIndicator = document.getElementById("loading_indicator");
if (loadingIndicator) { if (loadingIndicator) {
loadingIndicator.remove(); loadingIndicator.remove();
} }
}, 10000); }, 10000);
}; };
</script> </script>
</body> </body>
</html> </html>