вроде как починил сферум, УБРАЛ РАМКУ У МЕДИА БЕЗ ТЕКСТА

This commit is contained in:
klockky
2025-11-20 00:16:08 +03:00
parent 3388b78f8c
commit 15440536b4
4 changed files with 1070 additions and 147 deletions

View File

@@ -1600,11 +1600,11 @@ class _ChatsScreenState extends State<ChatsScreen>
}
void _showSferumWebView(BuildContext context, String url) {
showModalBottomSheet(
context: context,
isScrollControlled: true,
backgroundColor: Colors.transparent,
builder: (context) => SferumWebViewPanel(url: url),
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => SferumWebViewPanel(url: url),
fullscreenDialog: true,
),
);
}
@@ -4039,116 +4039,269 @@ class SferumWebViewPanel extends StatefulWidget {
class _SferumWebViewPanelState extends State<SferumWebViewPanel> {
bool _isLoading = true;
InAppWebViewController? _webViewController;
Future<void> _checkCanGoBack() async {
}
Future<void> _goBack() async {
if (_webViewController != null && await _webViewController!.canGoBack()) {
await _webViewController!.goBack();
_checkCanGoBack();
} else {
if (mounted) {
Navigator.of(context).pop();
}
}
}
@override
Widget build(BuildContext context) {
final colors = Theme.of(context).colorScheme;
return DraggableScrollableSheet(
initialChildSize: 0.9,
minChildSize: 0.5,
maxChildSize: 0.95,
builder: (context, scrollController) {
return Container(
decoration: BoxDecoration(
color: colors.surface,
borderRadius: const BorderRadius.vertical(top: Radius.circular(20)),
return Scaffold(
backgroundColor: colors.surface,
appBar: AppBar(
backgroundColor: colors.surface,
elevation: 0,
leading: IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: _goBack,
),
title: Row(
children: [
Image.asset(
'assets/images/spermum.png',
width: 28,
height: 28,
),
const SizedBox(width: 12),
const Text(
'Сферум',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w600,
),
),
],
),
actions: [
IconButton(
icon: const Icon(Icons.close),
onPressed: () => Navigator.of(context).pop(),
tooltip: 'Закрыть',
),
child: Column(
children: [
Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
color: colors.outline.withOpacity(0.2),
width: 1,
),
],
),
body: Stack(
children: [
if (!Platform.isLinux)
InAppWebView(
initialUrlRequest: URLRequest(url: WebUri(widget.url)),
initialSettings: InAppWebViewSettings(
javaScriptEnabled: true,
transparentBackground: true,
useShouldOverrideUrlLoading: true,
useOnLoadResource: false,
useOnDownloadStart: false,
cacheEnabled: true,
verticalScrollBarEnabled: true,
horizontalScrollBarEnabled: true,
supportZoom: false,
disableVerticalScroll: false,
disableHorizontalScroll: false,
allowsInlineMediaPlayback: true,
mediaPlaybackRequiresUserGesture: false,
allowsBackForwardNavigationGestures: true,
useHybridComposition: true,
supportMultipleWindows: false,
javaScriptCanOpenWindowsAutomatically: false,
),
onWebViewCreated: (controller) {
_webViewController = controller;
},
onCreateWindow: (controller, createWindowAction) async {
final uri = createWindowAction.request.url;
print('🪟 Попытка открыть новое окно: $uri');
if (uri != null) {
await controller.loadUrl(urlRequest: URLRequest(url: uri));
}
return true;
},
shouldOverrideUrlLoading: (controller, navigationAction) async {
final uri = navigationAction.request.url;
final navigationType = navigationAction.navigationType;
print('🔗 Попытка перехода по ссылке: $uri (тип: $navigationType)');
if (navigationType == NavigationType.LINK_ACTIVATED) {
return NavigationActionPolicy.ALLOW;
}
return NavigationActionPolicy.ALLOW;
},
onLoadStart: (controller, url) async {
print('🌐 WebView начало загрузки: $url');
setState(() {
_isLoading = true;
});
try {
await controller.evaluateJavascript(source: '''
// Переопределяем window.open сразу
if (window.open.toString().indexOf('native code') === -1) {
var originalOpen = window.open;
window.open = function(url, name, features) {
if (url && typeof url === 'string') {
window.location.href = url;
return null;
}
return originalOpen.apply(this, arguments);
};
}
''');
} catch (e) {
print('⚠️ Ошибка при выполнении JavaScript в onLoadStart: $e');
}
},
onLoadStop: (controller, url) async {
print('✅ WebView загрузка завершена: $url');
setState(() {
_isLoading = false;
});
_checkCanGoBack();
try {
await controller.evaluateJavascript(source: '''
// Включаем прокрутку
document.body.style.overflow = 'auto';
document.documentElement.style.overflow = 'auto';
document.body.style.webkitOverflowScrolling = 'touch';
document.body.style.position = 'relative';
document.documentElement.style.position = 'relative';
// Перехватываем все клики по ссылкам и принудительно открываем в том же окне
(function() {
// Функция для обработки ссылок
function processLink(link) {
if (link && link.tagName === 'A') {
var href = link.getAttribute('href');
if (href && !href.startsWith('javascript:') && !href.startsWith('mailto:')) {
// Убираем target="_blank" если есть
link.removeAttribute('target');
// Добавляем обработчик клика
link.addEventListener('click', function(e) {
var href = this.getAttribute('href');
if (href && !href.startsWith('javascript:') && !href.startsWith('mailto:')) {
e.preventDefault();
e.stopPropagation();
window.location.href = href;
return false;
}
}, true);
}
}
}
// Обрабатываем все существующие ссылки
function processAllLinks() {
var links = document.querySelectorAll('a');
for (var i = 0; i < links.length; i++) {
processLink(links[i]);
}
}
// Обрабатываем ссылки при загрузке
processAllLinks();
// Перехватываем клики на уровне document
document.addEventListener('click', function(e) {
var target = e.target;
// Находим ближайшую ссылку
while (target && target.tagName !== 'A' && target !== document.body) {
target = target.parentElement;
}
if (target && target.tagName === 'A') {
var href = target.getAttribute('href');
if (href && !href.startsWith('javascript:') && !href.startsWith('mailto:')) {
// Убираем target если есть
target.removeAttribute('target');
// Открываем в том же окне
e.preventDefault();
e.stopPropagation();
window.location.href = href;
return false;
}
}
}, true);
// Отслеживаем динамически добавляемые ссылки
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
mutation.addedNodes.forEach(function(node) {
if (node.nodeType === 1) { // Element node
if (node.tagName === 'A') {
processLink(node);
}
// Обрабатываем ссылки внутри добавленного элемента
var links = node.querySelectorAll ? node.querySelectorAll('a') : [];
for (var i = 0; i < links.length; i++) {
processLink(links[i]);
}
}
});
});
});
// Начинаем наблюдение за изменениями в DOM
observer.observe(document.body, {
childList: true,
subtree: true
});
// Переопределяем window.open чтобы открывать в том же окне
var originalOpen = window.open;
window.open = function(url, name, features) {
if (url && typeof url === 'string') {
window.location.href = url;
return null;
}
return originalOpen.apply(this, arguments);
};
})();
''');
} catch (e) {
print('⚠️ Ошибка при выполнении JavaScript: $e');
}
},
onReceivedError: (controller, request, error) {
print(
'❌ WebView ошибка: ${error.description} (${error.type})',
);
},
onConsoleMessage: (controller, consoleMessage) {
print('📝 Console: ${consoleMessage.message}');
},
),
if (Platform.isLinux)
Container(
color: colors.surface,
child: const Center(
child: Text(
'Сферум временно не доступен на линуксе,\nмы думаем как это исправить.',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w600,
),
),
child: Row(
children: [
Image.asset(
'assets/images/spermum.png',
width: 28,
height: 28,
),
const SizedBox(width: 12),
const Text(
'Сферум',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w600,
),
),
const Spacer(),
IconButton(
icon: const Icon(Icons.close),
onPressed: () => Navigator.of(context).pop(),
),
],
),
),
),
Expanded(
child: Stack(
children: [
if (!Platform.isLinux)
InAppWebView(
initialUrlRequest: URLRequest(url: WebUri(widget.url)),
initialSettings: InAppWebViewSettings(
javaScriptEnabled: true,
transparentBackground: true,
useShouldOverrideUrlLoading: false,
useOnLoadResource: false,
useOnDownloadStart: false,
cacheEnabled: true,
),
onLoadStart: (controller, url) {
print('🌐 WebView начало загрузки: $url');
setState(() {
_isLoading = true;
});
},
onLoadStop: (controller, url) {
print('✅ WebView загрузка завершена: $url');
setState(() {
_isLoading = false;
});
},
onReceivedError: (controller, request, error) {
print(
'❌ WebView ошибка: ${error.description} (${error.type})',
);
},
),
if (Platform.isLinux)
Container(
color: colors.surface,
child: const Center(
child: Text(
'Сферум временно не доступен на линуксе,\nмы думаем как это исправить.',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w600,
),
),
),
),
if (_isLoading && !Platform.isLinux)
Container(
color: colors.surface,
child: const Center(child: CircularProgressIndicator()),
),
],
),
),
],
),
);
},
if (_isLoading && !Platform.isLinux)
Container(
color: colors.surface,
child: const Center(child: CircularProgressIndicator()),
),
],
),
);
}
}