Open NelepovDmitry opened 1 year ago
Give the option to disable close by gesture - this will solve all the problems
Give the option to disable close by gesture - this will solve all the problems
For example?
I've investigated @tapswap_bot (props to them) source code (webkit debug) and found the solution. I've also made the scrolling working (their solution was breaking it).
So steps to implement:
(tailwind style) document: h-auto, overflow-hidden body: min-h-screen h-screen overflow-hidden
js code:
const overflow = 100
document.body.style.overflowY = 'hidden'
document.body.style.marginTop = `${overflow}px`
document.body.style.height = window.innerHeight + overflow + "px"
document.body.style.paddingBottom = `${overflow}px`
window.scrollTo(0, overflow)
let ts: number | undefined
const onTouchStart = (e: TouchEvent) => {
ts = e.touches[0].clientY
}
const onTouchMove = (e: TouchEvent) => {
if (scrollableEl) {
const scroll = scrollableEl.scrollTop
const te = e.changedTouches[0].clientY
if (scroll <= 0 && ts! < te) {
e.preventDefault()
}
} else {
e.preventDefault()
}
}
document.documentElement.addEventListener('touchstart', onTouchStart, { passive: false })
document.documentElement.addEventListener('touchmove', onTouchMove, { passive: false })
After that it works perfectly, no rage scroll breaks it. The only concern is that maybe some device has reversed scroll direction, in that case we will need to reverse touchmove condition logic, but anyway - it's working.
I've investigated @tapswap_bot (props to them) source code (webkit debug) and found the solution. I've also made the scrolling working (their solution was breaking it).
So steps to implement:
- Document/body magic (without this touchmove step doesn't fix the problem for some reason):
(tailwind style) document: h-auto, overflow-hidden body: min-h-screen h-screen overflow-hidden
js code:
const overflow = 100 document.body.style.overflowY = 'hidden' document.body.style.marginTop = `${overflow}px` document.body.style.height = window.innerHeight + overflow + "px" document.body.style.paddingBottom = `${overflow}px` window.scrollTo(0, overflow)
- Block touchmove (block scroll on doc and body, because of the first step. Make body's child scrollable and then...):
let ts: number | undefined const onTouchStart = (e: TouchEvent) => { ts = e.touches[0].clientY } const onTouchMove = (e: TouchEvent) => { if (scrollableEl) { const scroll = scrollableEl.scrollTop const te = e.changedTouches[0].clientY if (scroll <= 0 && ts! < te) { e.preventDefault() } } else { e.preventDefault() } } document.documentElement.addEventListener('touchstart', onTouchStart, { passive: false }) document.documentElement.addEventListener('touchmove', onTouchMove, { passive: false })
After that it works perfectly, no rage scroll breaks it. The only concern is that maybe some device has reversed scroll direction, in that case we will need to reverse touchmove condition logic, but anyway - it's working.
Hi! I've tryied to use your solution, but i couldn't figure out, how to use it properly. My page just get's stuck in place. I have changed scrollableEl to the one i have, but it still doesn't work. If you could write a more detailed guide I would appreciate it. Btw I'm using React. Thanks!
Hi @Murik1502 ! We use React too (NextJS) and that's my code:
import AwaiterStyles from './Awaiter.module.scss'
export function Awaiter() {
const [tgReady, setTGReady] = useState(false)
useEffect(() => {
if (!tgReady) return
if (window.tgAppInited) return
window.tgAppInited = true
const scrollableEl = document.getElementById('app-scrollable')
const tg = window.Telegram.WebApp
tg.expand()
const overflow = 100
function setupDocument(enable: boolean) {
if (enable) {
document.documentElement.classList.add(AwaiterStyles.html)
document.body.style.marginTop = `${overflow}px`
document.body.style.height = window.innerHeight + overflow + "px"
document.body.style.paddingBottom = `${overflow}px`
window.scrollTo(0, overflow)
} else {
document.documentElement.classList.remove(AwaiterStyles.html)
document.body.style.removeProperty('marginTop')
document.body.style.removeProperty('height')
document.body.style.removeProperty('paddingBottom')
window.scrollTo(0, 0)
}
}
setupDocument(true)
let ts: number | undefined
const onTouchStart = (e: TouchEvent) => {
ts = e.touches[0].clientY
}
const onTouchMove = (e: TouchEvent) => {
if (scrollableEl) {
const scroll = scrollableEl.scrollTop
const te = e.changedTouches[0].clientY
if (scroll <= 0 && ts! < te) {
e.preventDefault()
}
} else {
e.preventDefault()
}
}
document.documentElement.addEventListener('touchstart', onTouchStart, { passive: false })
document.documentElement.addEventListener('touchmove', onTouchMove, { passive: false })
const onScroll = () => {
if (window.scrollY < overflow) {
window.scrollTo(0, overflow)
if (scrollableEl) {
scrollableEl.scrollTo(0, 0)
}
}
}
window.addEventListener('scroll', onScroll, { passive: true })
// authorize here
return () => {
setupDocument(false)
document.documentElement.removeEventListener('touchstart', onTouchStart)
document.documentElement.removeEventListener('touchmove', onTouchMove)
window.removeEventListener('scroll', onScroll)
}
}, [tgReady])
return <>
<Script
src='/js/telegram-web-app.min.js'
onLoad={() => {
setTGReady(true)
}}
/>
</>
}
Styles:
.html {
@apply h-auto overflow-hidden;
body {
@apply min-h-screen h-screen overflow-hidden isolate;
}
}
HTML tree is the following: html > body > div#app-scrollable
You can inspect our bot further, if you want to compare it with yours: @OGCommunityBot
Hi @maybephilipp! Thanks a lot for your response. I have only one question: where do you call your Awaiter function?
BTW, your app looks so sick! Great job
I have only one question: where do you call your Awaiter function?
@Murik1502 I call it in a root layout right after opening "html" tag: <Awaiter />
. But the placement doesn't really make any difference - it just need to be loaded on the page. While it's loading or not inserted I show a full page loader.
It could be a hook, but for us the tg script is optional, so we insert this RJX element conditionally.
Has anyone tried this solution with Flutter Web? It seems like scrollTo doesn't work after loading, leaving a white stripe. Nothing helped.
@maybephilipp Thanks, thats the best solution so far. 🎉
@maybephilipp one question, I am just facing an issue with this solution, when there is a fixed sized scrollable container on the page (in my case a modal), which does not change the scrollTop position of the wrapper. You can scroll the content of the container up, but not down 😅
I'm using this code and it's working fine but I'm having trouble with the scroll parts, they're completely disabled on mobile!
We have project on JS, how we can rewrite this code on JS? Meybe someone already try it?
Telegram Flutter scrolling bug Platforms - Android & iOS
Steps to reproduce
1.Create Flutter app with a simple ListView (like ListView.builder for example) 2.Deploy it on any host (or for test use https://todo.hubitproject.com/flutter_bug_ck) 3.Create Telegram bot or check test bot @hubit_test_flutter_bot 3.1. Open Telegram bot father @Botfather 3.2. Type /newbot 3.3. Enter a unique name 3.3. Enter a unique bot login 3.4. Type /setmenubutton 3.5. Enter a path to flutter app from step 2 (or for test use https://todo.hubitproject.com/flutter_bug_ck) 3.6. Enter button name, for example "Test Flutter" 4.Open bot from Mobile device 5.Tap button from step 3.6 6.Expand Web App to fullscreen by dragging topbar part of webapp
Actual result Scrolling down is close telegram web app
Complete code of app deployed at https://todo.hubitproject.com/flutter_bug_ck
import 'dart:math';
import 'package:flutter/material.dart';
void main() { runApp(const MyApp()); }
class MyApp extends StatelessWidget { const MyApp({super.key});
// This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: const HomeScreen(), ); } }
class HomeScreen extends StatefulWidget { const HomeScreen({super.key});
@override State createState() => _HomeScreenState();
}
class _HomeScreenState extends State {
@override
Widget build(BuildContext context) {
return Scaffold(
body: ListView.separated(
itemBuilder: (context, index) {
return Container(
padding: const EdgeInsets.all(32),
color: Color.fromARGB(
255,
Random().nextInt(255),
Random().nextInt(255),
Random().nextInt(255),
),
child: Text('Item $index'),
);
},
separatorBuilder: (context, index) {
return const SizedBox(
height: 32,
);
},
itemCount: 100),
);
}
}
flutter doctor -v result
[✓] Flutter (Channel stable, 3.3.10, on macOS 13.1 22C65 darwin-arm, locale en-RU) • Flutter version 3.3.10 on channel stable at /Users/rain/Dev/flutter • Upstream repository https://github.com/flutter/flutter.git • Framework revision 135454af32 (2 months ago), 2022-12-15 07:36:55 -0800 • Engine revision 3316dd8728 • Dart version 2.18.6 • DevTools version 2.15.0
[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.0) • Android SDK at /Users/rain/Library/Android/sdk • Platform android-33, build-tools 33.0.0 • Java binary at: /Applications/Android Studio.app/Contents/jre/Contents/Home/bin/java • Java version OpenJDK Runtime Environment (build 11.0.13+0-b1751.21-8125866) • All Android licenses accepted.
[✓] Xcode - develop for iOS and macOS (Xcode 14.2) • Xcode at /Applications/Xcode.app/Contents/Developer • Build 14C18 • CocoaPods version 1.11.3
[✓] Chrome - develop for the web • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
[✓] Android Studio (version 2021.3) • Android Studio at /Applications/Android Studio.app/Contents • Flutter plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/9212-flutter • Dart plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/6351-dart • Java version OpenJDK Runtime Environment (build 11.0.13+0-b1751.21-8125866)
[✓] IntelliJ IDEA Community Edition (version 2022.3.2) • IntelliJ at /Applications/IntelliJ IDEA CE.app • Flutter plugin version 72.0.4 • Dart plugin version 223.8617.8
[✓] VS Code (version 1.75.1) • VS Code at /Applications/Visual Studio Code.app/Contents • Flutter extension can be installed from: 🔨 https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter
[✓] Connected device (2 available) • macOS (desktop) • macos • darwin-arm64 • macOS 13.1 22C65 darwin-arm • Chrome (web) • chrome • web-javascript • Google Chrome 109.0.5414.119
[✓] HTTP Host Availability • All required HTTP hosts are available
• No issues found!