1
0

Фронт правки

1. Улучшено отображение на iphone и android в PWA
This commit is contained in:
2026-01-17 09:25:10 +07:00
parent c46fd3952e
commit aca5eb84fd
7 changed files with 40 additions and 22 deletions

View File

@@ -68,12 +68,15 @@ body {
/* Мобильный режим */ /* Мобильный режим */
body.is-mobile { body.is-mobile {
overflow: hidden; overflow: hidden;
touch-action: none; /* Блокируем overscroll (pull-to-refresh), но разрешаем touch внутри приложения */
overscroll-behavior: none;
} }
body.is-mobile #app { body.is-mobile #app {
height: 100dvh; height: 100dvh;
overflow: hidden; overflow: hidden;
/* Убираем градиент на мобильных - сплошной цвет */
background: var(--bg-body);
} }
/* Safe area для iPhone (notch и home indicator) */ /* Safe area для iPhone (notch и home indicator) */
@@ -102,12 +105,11 @@ body.is-mobile .pwa-safe-wrapper {
/* transform создаёт containing block - fixed элементы внутри /* transform создаёт containing block - fixed элементы внутри
теперь позиционируются относительно wrapper, а не viewport */ теперь позиционируются относительно wrapper, а не viewport */
transform: translateZ(0); transform: translateZ(0);
/* Смещаем градиент вверх чтобы он продолжал ::before без шва */ /* Убираем градиент на мобильных - сплошной цвет */
background-size: 100vw 100vh; background: var(--bg-body);
background-position: 0 calc(-1 * var(--safe-area-top));
} }
/* Полоска с градиентом под статус-баром iPhone */ /* Полоска под статус-баром iPhone */
@supports (padding-top: env(safe-area-inset-top)) { @supports (padding-top: env(safe-area-inset-top)) {
body.is-mobile::before { body.is-mobile::before {
content: ''; content: '';
@@ -116,10 +118,8 @@ body.is-mobile .pwa-safe-wrapper {
left: 0; left: 0;
right: 0; right: 0;
height: var(--safe-area-top); height: var(--safe-area-top);
/* Тот же градиент что и на странице, но растянутый на весь viewport */ /* Сплошной цвет вместо градиента */
background: var(--bg-gradient); background: var(--bg-body);
background-size: 100vw 100vh;
background-position: top center;
z-index: 99999; z-index: 99999;
pointer-events: none; pointer-events: none;
} }
@@ -129,6 +129,7 @@ body.is-mobile .pwa-safe-wrapper {
/* Убрали position: fixed - он конфликтует с pwa-safe-wrapper */ /* Убрали position: fixed - он конфликтует с pwa-safe-wrapper */
body.panel-open { body.panel-open {
overflow: hidden !important; overflow: hidden !important;
touch-action: none !important; /* Используем overscroll-behavior вместо touch-action: none для PWA совместимости */
overscroll-behavior: none !important;
} }
</style> </style>

View File

@@ -410,9 +410,10 @@ defineExpose({ saveTask, deleteTask, archiveTask })
-webkit-overflow-scrolling: touch; -webkit-overflow-scrolling: touch;
scrollbar-width: none; scrollbar-width: none;
-ms-overflow-style: none; -ms-overflow-style: none;
/* Отключаем вертикальный скролл на уровне этого элемента */ /* Предотвращаем системные жесты (pull-to-refresh) */
overscroll-behavior: contain; overscroll-behavior: contain;
touch-action: pan-x; /* Разрешаем и горизонтальный и вертикальный pan - колонки внутри скроллятся вертикально */
touch-action: pan-x pan-y;
} }
.board.mobile .columns::-webkit-scrollbar { .board.mobile .columns::-webkit-scrollbar {

View File

@@ -109,8 +109,6 @@ const handleTouchStart = (e) => {
longPressTimer = setTimeout(() => { longPressTimer = setTimeout(() => {
isLongPressing.value = true isLongPressing.value = true
// Предотвращаем стандартное поведение (выделение текста, контекстное меню)
e.preventDefault()
// Вибрация если поддерживается // Вибрация если поддерживается
if (navigator.vibrate) { if (navigator.vibrate) {
navigator.vibrate(30) navigator.vibrate(30)

View File

@@ -524,7 +524,7 @@ watch(isOpen, () => {
.mobile-calendar-overlay { .mobile-calendar-overlay {
position: fixed; position: fixed;
inset: 0; inset: 0;
background: #18181b; background: var(--bg-body);
z-index: 2000; z-index: 2000;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@@ -534,7 +534,7 @@ watch(isOpen, () => {
.mobile-calendar-panel { .mobile-calendar-panel {
width: 100%; width: 100%;
height: 100%; height: 100%;
background: #18181b; background: var(--bg-body);
display: flex; display: flex;
flex-direction: column; flex-direction: column;
overflow: hidden; overflow: hidden;
@@ -543,6 +543,8 @@ watch(isOpen, () => {
.mobile-calendar-body { .mobile-calendar-body {
flex: 1; flex: 1;
padding: 20px 16px; padding: 20px 16px;
/* Safe area для iPhone notch */
padding-top: calc(20px + env(safe-area-inset-top, 0px));
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }

View File

@@ -39,7 +39,7 @@
</template> </template>
<script setup> <script setup>
import { ref, computed, watch, onMounted, onUpdated } from 'vue' import { ref, computed, watch, onMounted, onUpdated, onUnmounted } from 'vue'
const props = defineProps({ const props = defineProps({
modelValue: { modelValue: {
@@ -106,6 +106,13 @@ watch(open, (val) => {
} }
}) })
// Cleanup при unmount — гарантируем сброс overflow
onUnmounted(() => {
if (open.value) {
document.body.style.overflow = ''
}
})
onMounted(refreshIcons) onMounted(refreshIcons)
onUpdated(refreshIcons) onUpdated(refreshIcons)
</script> </script>
@@ -223,6 +230,8 @@ onUpdated(refreshIcons)
display: flex; display: flex;
flex-direction: column; flex-direction: column;
overflow: hidden; overflow: hidden;
/* Safe area для iPhone notch */
padding-top: env(safe-area-inset-top, 0px);
} }
.panel-header { .panel-header {

View File

@@ -39,7 +39,7 @@
</template> </template>
<script setup> <script setup>
import { watch, onMounted, onUpdated } from 'vue' import { watch, onMounted, onUpdated, onUnmounted } from 'vue'
const props = defineProps({ const props = defineProps({
open: { open: {
@@ -99,6 +99,13 @@ watch(() => props.open, (val) => {
} }
}) })
// Cleanup при unmount — гарантируем сброс overflow
onUnmounted(() => {
if (props.open) {
document.body.style.overflow = ''
}
})
onMounted(refreshIcons) onMounted(refreshIcons)
onUpdated(refreshIcons) onUpdated(refreshIcons)
</script> </script>

View File

@@ -353,10 +353,8 @@ onUnmounted(() => {
border-radius: 0; border-radius: 0;
touch-action: pan-y pinch-zoom; touch-action: pan-y pinch-zoom;
overscroll-behavior: contain; overscroll-behavior: contain;
/* Градиент как на основной странице */ /* Сплошной цвет вместо градиента */
background: var(--bg-gradient); background: var(--bg-body);
background-size: 100vw 100vh;
background-position: 0 calc(-1 * var(--safe-area-top));
} }
.panel.mobile .resize-handle { .panel.mobile .resize-handle {
@@ -376,6 +374,8 @@ onUnmounted(() => {
.panel.mobile .panel-footer { .panel.mobile .panel-footer {
padding: 16px; padding: 16px;
/* Safe area для iPhone home indicator */
padding-bottom: calc(16px + env(safe-area-inset-bottom, 0px));
} }
.panel.mobile .header-content :deep(h2) { .panel.mobile .header-content :deep(h2) {