143 lines
4.2 KiB
Dart
143 lines
4.2 KiB
Dart
import 'dart:convert';
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
const double roomGameDesignWidth = 750;
|
|
|
|
double resolveRoomGameAvailableHeight(
|
|
BuildContext context, {
|
|
double reservedTop = 12,
|
|
}) {
|
|
final mediaQuery = MediaQuery.maybeOf(context);
|
|
if (mediaQuery == null) {
|
|
return 0;
|
|
}
|
|
|
|
final bottomInset =
|
|
mediaQuery.viewInsets.bottom > mediaQuery.padding.bottom
|
|
? mediaQuery.viewInsets.bottom
|
|
: mediaQuery.padding.bottom;
|
|
final availableHeight =
|
|
mediaQuery.size.height -
|
|
mediaQuery.padding.top -
|
|
bottomInset -
|
|
reservedTop;
|
|
if (!availableHeight.isFinite || availableHeight <= 0) {
|
|
return mediaQuery.size.height;
|
|
}
|
|
return availableHeight.clamp(0.0, mediaQuery.size.height).toDouble();
|
|
}
|
|
|
|
double clampRoomGameHeight(
|
|
double value,
|
|
double maxHeight, {
|
|
double minHeight = 0,
|
|
}) {
|
|
if (!value.isFinite || value <= 0) {
|
|
return maxHeight > 0 ? maxHeight : 0;
|
|
}
|
|
if (!maxHeight.isFinite || maxHeight <= 0) {
|
|
return value;
|
|
}
|
|
if (minHeight > maxHeight) {
|
|
return maxHeight;
|
|
}
|
|
return value.clamp(minHeight, maxHeight).toDouble();
|
|
}
|
|
|
|
String resolveRoomGameScreenMode(
|
|
Map<String, dynamic> launchParams, {
|
|
required bool fullScreen,
|
|
}) {
|
|
final candidates = <String>[
|
|
launchParams['screenMode']?.toString() ?? '',
|
|
launchParams['screen_mode']?.toString() ?? '',
|
|
launchParams['displayMode']?.toString() ?? '',
|
|
launchParams['gameScreenMode']?.toString() ?? '',
|
|
];
|
|
for (final candidate in candidates) {
|
|
final trimmed = candidate.trim();
|
|
if (trimmed.isNotEmpty) {
|
|
return trimmed.toLowerCase();
|
|
}
|
|
}
|
|
return fullScreen ? 'full' : 'half';
|
|
}
|
|
|
|
String buildRoomGameNativeFitScript({
|
|
required double visibleHeight,
|
|
required double expectedHeight,
|
|
}) {
|
|
final options = jsonEncode(<String, dynamic>{
|
|
'visibleHeight': _roundMetric(visibleHeight),
|
|
'expectedHeight': _roundMetric(expectedHeight),
|
|
});
|
|
return '''
|
|
(function() {
|
|
const options = $options;
|
|
const fitKey = '__roomGameNativeViewportFit';
|
|
|
|
function applyFit() {
|
|
try {
|
|
const visibleHeight = Number(options.visibleHeight) || window.innerHeight || 0;
|
|
const expectedHeight = Number(options.expectedHeight) || 0;
|
|
if (!document.body || !visibleHeight || !expectedHeight) {
|
|
return;
|
|
}
|
|
|
|
const rawScale = visibleHeight / expectedHeight;
|
|
const scale = Math.min(1, rawScale);
|
|
window[fitKey] = {
|
|
scale: scale,
|
|
visibleHeight: visibleHeight,
|
|
expectedHeight: expectedHeight,
|
|
compact: scale < 0.999
|
|
};
|
|
|
|
if (scale >= 0.999) {
|
|
document.documentElement.style.overflow = '';
|
|
document.body.style.overflow = '';
|
|
document.body.style.transform = '';
|
|
document.body.style.transformOrigin = '';
|
|
document.body.style.width = '';
|
|
document.body.style.minHeight = '';
|
|
document.documentElement.removeAttribute('data-room-game-native-fit');
|
|
return;
|
|
}
|
|
|
|
document.documentElement.setAttribute('data-room-game-native-fit', 'true');
|
|
document.documentElement.style.overflow = 'hidden';
|
|
document.body.style.overflow = 'hidden';
|
|
document.body.style.transform = 'scale(' + scale + ')';
|
|
document.body.style.transformOrigin = 'top left';
|
|
document.body.style.width = (100 / scale) + '%';
|
|
document.body.style.minHeight = expectedHeight + 'px';
|
|
} catch (_) {}
|
|
}
|
|
|
|
if (document.readyState === 'loading') {
|
|
document.addEventListener('DOMContentLoaded', applyFit, { once: true });
|
|
} else {
|
|
applyFit();
|
|
}
|
|
[50, 250, 800, 1600, 3000].forEach(function(delay) {
|
|
window.setTimeout(applyFit, delay);
|
|
});
|
|
if (!window.__roomGameNativeFitResizeReady) {
|
|
window.__roomGameNativeFitResizeReady = true;
|
|
window.addEventListener('resize', applyFit, true);
|
|
window.addEventListener('orientationchange', function() {
|
|
window.setTimeout(applyFit, 120);
|
|
}, true);
|
|
}
|
|
})();
|
|
''';
|
|
}
|
|
|
|
double _roundMetric(double value) {
|
|
if (!value.isFinite) {
|
|
return 0;
|
|
}
|
|
return double.parse(value.toStringAsFixed(2));
|
|
}
|