Compare commits
2 commits
61e2911706
...
cab6314bc7
| Author | SHA1 | Date | |
|---|---|---|---|
| cab6314bc7 | |||
| cb067f3785 |
71 changed files with 2273 additions and 115 deletions
|
|
@ -7,8 +7,8 @@ android {
|
||||||
applicationId "olcxja.miarven"
|
applicationId "olcxja.miarven"
|
||||||
minSdkVersion rootProject.ext.minSdkVersion
|
minSdkVersion rootProject.ext.minSdkVersion
|
||||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||||
versionCode 3
|
versionCode 5
|
||||||
versionName "0.1.2"
|
versionName "0.1.4"
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
aaptOptions {
|
aaptOptions {
|
||||||
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
|
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
|
||||||
|
|
|
||||||
|
|
@ -310,5 +310,19 @@
|
||||||
"error.call.screen": "screen share error: {0} :c",
|
"error.call.screen": "screen share error: {0} :c",
|
||||||
"error.call.screen.unsupported": "ur browser doesn't support screen sharing :c",
|
"error.call.screen.unsupported": "ur browser doesn't support screen sharing :c",
|
||||||
"label.stream.cam": "cam",
|
"label.stream.cam": "cam",
|
||||||
"label.stream.screen": "screen"
|
"label.stream.screen": "screen",
|
||||||
|
"action.call.settings": "voice settings :3",
|
||||||
|
"label.voice.microphone": "microphone",
|
||||||
|
"label.voice.speaker": "speaker",
|
||||||
|
"label.voice.camera": "camera",
|
||||||
|
"label.voice.camera.quality": "camera quality",
|
||||||
|
"label.voice.camera.fps": "camera fps",
|
||||||
|
"label.voice.screen.quality": "screen quality",
|
||||||
|
"label.voice.screen.fps": "screen fps",
|
||||||
|
"label.voice.sensitivity": "input sensitivity",
|
||||||
|
"label.voice.default": "default",
|
||||||
|
"error.call.microphone": "microphone error :c",
|
||||||
|
"error.voice.reconnect.failed": "voice connection lost :c",
|
||||||
|
"error.voice.ticket.rejected": "voice auth failed :c check VOICE_KEY/server version",
|
||||||
|
"error.voice.not.configured": "voice server not configured :c missing VOICE_KEY"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -319,5 +319,19 @@
|
||||||
"error.call.screen": "Screen share error: {0}",
|
"error.call.screen": "Screen share error: {0}",
|
||||||
"error.call.screen.unsupported": "Screen sharing is not supported on this browser.",
|
"error.call.screen.unsupported": "Screen sharing is not supported on this browser.",
|
||||||
"label.stream.cam": "Cam",
|
"label.stream.cam": "Cam",
|
||||||
"label.stream.screen": "Screen"
|
"label.stream.screen": "Screen",
|
||||||
|
"action.call.settings": "Voice settings",
|
||||||
|
"label.voice.microphone": "Microphone",
|
||||||
|
"label.voice.speaker": "Speaker",
|
||||||
|
"label.voice.camera": "Camera",
|
||||||
|
"label.voice.camera.quality": "Camera quality",
|
||||||
|
"label.voice.camera.fps": "Camera FPS",
|
||||||
|
"label.voice.screen.quality": "Screenshare quality",
|
||||||
|
"label.voice.screen.fps": "Screenshare FPS",
|
||||||
|
"label.voice.sensitivity": "Input sensitivity",
|
||||||
|
"label.voice.default": "Default",
|
||||||
|
"error.call.microphone": "Microphone error",
|
||||||
|
"error.voice.reconnect.failed": "Voice connection lost",
|
||||||
|
"error.voice.ticket.rejected": "Voice authentication failed - check VOICE_KEY/server version",
|
||||||
|
"error.voice.not.configured": "Voice server is not configured (missing VOICE_KEY)"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -319,5 +319,19 @@
|
||||||
"error.call.screen": "Błąd udostępniania ekranu: {0}",
|
"error.call.screen": "Błąd udostępniania ekranu: {0}",
|
||||||
"error.call.screen.unsupported": "Udostępnianie ekranu nie jest obsługiwane w tej przeglądarce.",
|
"error.call.screen.unsupported": "Udostępnianie ekranu nie jest obsługiwane w tej przeglądarce.",
|
||||||
"label.stream.cam": "Kamera",
|
"label.stream.cam": "Kamera",
|
||||||
"label.stream.screen": "Ekran"
|
"label.stream.screen": "Ekran",
|
||||||
|
"action.call.settings": "Ustawienia rozmowy",
|
||||||
|
"label.voice.microphone": "Mikrofon",
|
||||||
|
"label.voice.speaker": "Głośnik",
|
||||||
|
"label.voice.camera": "Kamera",
|
||||||
|
"label.voice.camera.quality": "Jakość kamery",
|
||||||
|
"label.voice.camera.fps": "FPS kamery",
|
||||||
|
"label.voice.screen.quality": "Jakość ekranu",
|
||||||
|
"label.voice.screen.fps": "FPS ekranu",
|
||||||
|
"label.voice.sensitivity": "Czułość wejścia",
|
||||||
|
"label.voice.default": "Domyślne",
|
||||||
|
"error.call.microphone": "Błąd mikrofonu",
|
||||||
|
"error.voice.reconnect.failed": "Utracono połączenie głosowe",
|
||||||
|
"error.voice.ticket.rejected": "Autoryzacja głosu nieudana - sprawdź VOICE_KEY/wersję serwera",
|
||||||
|
"error.voice.not.configured": "Serwer głosowy nieskonfigurowany (brak VOICE_KEY)"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2472,6 +2472,7 @@ let touchEndX = 0;
|
||||||
let touchStartY = 0;
|
let touchStartY = 0;
|
||||||
let touchEndY = 0;
|
let touchEndY = 0;
|
||||||
let touchMoved = false;
|
let touchMoved = false;
|
||||||
|
let touchStartTarget = null;
|
||||||
|
|
||||||
let pressDate;
|
let pressDate;
|
||||||
|
|
||||||
|
|
@ -2479,6 +2480,7 @@ document.addEventListener('touchstart', e => {
|
||||||
touchStartX = e.changedTouches[0].screenX;
|
touchStartX = e.changedTouches[0].screenX;
|
||||||
touchStartY = e.changedTouches[0].screenY;
|
touchStartY = e.changedTouches[0].screenY;
|
||||||
touchMoved = false;
|
touchMoved = false;
|
||||||
|
touchStartTarget = e.target;
|
||||||
|
|
||||||
activeTouchButton = e.target.closest('button, input, textarea');
|
activeTouchButton = e.target.closest('button, input, textarea');
|
||||||
if (activeTouchButton) {
|
if (activeTouchButton) {
|
||||||
|
|
@ -2558,6 +2560,18 @@ document.addEventListener('contextmenu', e => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Swipes that begin inside floating layers (popups, dialogs, dropdowns -
|
||||||
|
// anything rendered with position: fixed) belong to those layers and must
|
||||||
|
// not trigger app navigation gestures.
|
||||||
|
function touchStartedInFloatingLayer() {
|
||||||
|
let el = touchStartTarget;
|
||||||
|
while (el && el !== document.body && el !== document.documentElement) {
|
||||||
|
if (getComputedStyle(el).position === 'fixed') return true;
|
||||||
|
el = el.parentElement;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
function handleMobileSwipe() {
|
function handleMobileSwipe() {
|
||||||
const rem = parseFloat(getComputedStyle(document.documentElement).fontSize);
|
const rem = parseFloat(getComputedStyle(document.documentElement).fontSize);
|
||||||
if (window.innerWidth > 55 * rem) return;
|
if (window.innerWidth > 55 * rem) return;
|
||||||
|
|
@ -2566,6 +2580,7 @@ function handleMobileSwipe() {
|
||||||
let diffY = touchEndY - touchStartY;
|
let diffY = touchEndY - touchStartY;
|
||||||
|
|
||||||
if (Math.abs(diffX) > Math.abs(diffY) && Math.abs(diffX) > 4 * rem) {
|
if (Math.abs(diffX) > Math.abs(diffY) && Math.abs(diffX) > 4 * rem) {
|
||||||
|
if (touchStartedInFloatingLayer()) return;
|
||||||
if (diffX > 0) {
|
if (diffX > 0) {
|
||||||
mobileNavBack();
|
mobileNavBack();
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -1715,6 +1715,230 @@ input:checked + .toggle-slider:before {
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* In-call Voice Device Settings Popup */
|
||||||
|
#voice-device-settings {
|
||||||
|
position: fixed;
|
||||||
|
/* left/top are set from JS (centered, viewport-clamped) so the opening
|
||||||
|
animation cannot shift the popup and the header can drag it directly */
|
||||||
|
width: min(24rem, calc(100vw - 2rem));
|
||||||
|
max-height: calc(100vh - 3rem);
|
||||||
|
background: var(--main-bg-color);
|
||||||
|
border: var(--border-width) solid var(--light-border-color);
|
||||||
|
border-radius: 0.9rem;
|
||||||
|
box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.5);
|
||||||
|
z-index: 10020;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
|
opacity: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
transform: scale(0.92);
|
||||||
|
transition:
|
||||||
|
opacity 0.15s ease,
|
||||||
|
transform 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||||
|
}
|
||||||
|
#voice-device-settings.show {
|
||||||
|
opacity: 1;
|
||||||
|
pointer-events: auto;
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
#vds-header {
|
||||||
|
height: 2.8rem;
|
||||||
|
flex-shrink: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 0 0.6rem 0 0.9375rem;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
background: rgba(255, 255, 255, 0.03);
|
||||||
|
border-bottom: var(--border-width) solid var(--light-border-color);
|
||||||
|
user-select: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
cursor: grab;
|
||||||
|
touch-action: none;
|
||||||
|
}
|
||||||
|
#vds-header:active {
|
||||||
|
cursor: grabbing;
|
||||||
|
}
|
||||||
|
#vds-header span {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
#vds-header svg {
|
||||||
|
pointer-events: none !important;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
#vds-close {
|
||||||
|
width: 2rem;
|
||||||
|
height: 2rem;
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
color: var(--darker-text-color);
|
||||||
|
border-radius: 0.6rem;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
#vds-close:hover {
|
||||||
|
background: rgba(255, 255, 255, 0.08);
|
||||||
|
color: var(--text-color);
|
||||||
|
}
|
||||||
|
#vds-body {
|
||||||
|
padding: 0.4rem 0.7rem 0.8rem;
|
||||||
|
overflow-y: auto;
|
||||||
|
touch-action: pan-y;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.15rem;
|
||||||
|
}
|
||||||
|
.vds-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.3rem;
|
||||||
|
padding: 0.3rem 0.1rem;
|
||||||
|
}
|
||||||
|
.vds-row > label {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--darker-text-color);
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
.vds-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 0.5rem;
|
||||||
|
padding: 0.3rem 0.1rem;
|
||||||
|
}
|
||||||
|
.vds-cell {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.3rem;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
.vds-cell > label {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--darker-text-color);
|
||||||
|
}
|
||||||
|
#voice-device-settings .custom-select {
|
||||||
|
margin: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 2.3rem;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Floating option layer for the settings selects - lives on <body>, so it can
|
||||||
|
escape the popup bounds and is unaffected by the popup transform/scrolling.
|
||||||
|
Explicit solid background: never translucent over call content. */
|
||||||
|
.custom-select-options.vds-floating {
|
||||||
|
position: fixed;
|
||||||
|
display: block;
|
||||||
|
width: auto;
|
||||||
|
margin: 0;
|
||||||
|
background-color: var(--main-bg-color);
|
||||||
|
z-index: 10040;
|
||||||
|
opacity: 0;
|
||||||
|
visibility: hidden;
|
||||||
|
pointer-events: none;
|
||||||
|
transform: translateY(-0.4rem);
|
||||||
|
transition:
|
||||||
|
opacity 0.15s ease,
|
||||||
|
transform 0.15s ease,
|
||||||
|
visibility 0.15s;
|
||||||
|
}
|
||||||
|
.custom-select-options.vds-floating.vds-open {
|
||||||
|
opacity: 1;
|
||||||
|
visibility: visible;
|
||||||
|
pointer-events: auto;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
.vds-sens-meter {
|
||||||
|
position: relative;
|
||||||
|
height: 1.9rem;
|
||||||
|
background: rgba(255, 255, 255, 0.06);
|
||||||
|
border-radius: 0.55rem;
|
||||||
|
overflow: hidden;
|
||||||
|
border: var(--border-width) solid var(--light-border-color);
|
||||||
|
}
|
||||||
|
.vds-sens-fill {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
height: 100%;
|
||||||
|
width: 0%;
|
||||||
|
background: rgba(255, 255, 255, 0.15);
|
||||||
|
transition: width 0.05s linear, background-color 0.2s;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
.vds-sens-mark {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
width: 2px;
|
||||||
|
margin-left: -1px;
|
||||||
|
background: rgba(255, 255, 255, 0.65);
|
||||||
|
border-radius: 1px;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
/* Settings button keeps its hover look while the settings popup is open */
|
||||||
|
#voice-btn-settings.active {
|
||||||
|
background: rgba(255, 255, 255, 0.1);
|
||||||
|
}
|
||||||
|
#vds-sens-slider {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
margin: 0;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
background: transparent;
|
||||||
|
outline: none;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 0.55rem;
|
||||||
|
/* pan-y on the popup body would eat horizontal touch drags */
|
||||||
|
touch-action: none;
|
||||||
|
z-index: 2;
|
||||||
|
cursor: ew-resize;
|
||||||
|
}
|
||||||
|
/* The app-wide `input:active` press effect must not shrink this slider. */
|
||||||
|
#vds-sens-slider:active,
|
||||||
|
#vds-sens-slider.is-pressed {
|
||||||
|
transform: none !important;
|
||||||
|
}
|
||||||
|
#vds-sens-slider::-webkit-slider-thumb {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
width: 0.25rem;
|
||||||
|
height: 100%;
|
||||||
|
background: var(--text-color);
|
||||||
|
border-radius: 0.125rem;
|
||||||
|
box-shadow: 0 0 0.3rem rgba(0, 0, 0, 0.8);
|
||||||
|
}
|
||||||
|
#vds-sens-slider::-webkit-slider-thumb:hover,
|
||||||
|
#vds-sens-slider::-webkit-slider-thumb:active {
|
||||||
|
transform: none !important;
|
||||||
|
}
|
||||||
|
#vds-sens-slider::-moz-range-thumb {
|
||||||
|
width: 0.25rem;
|
||||||
|
height: 100%;
|
||||||
|
background: var(--text-color);
|
||||||
|
border: none;
|
||||||
|
border-radius: 0.125rem;
|
||||||
|
}
|
||||||
|
#vds-sens-slider::-moz-range-thumb:hover,
|
||||||
|
#vds-sens-slider::-moz-range-thumb:active {
|
||||||
|
transform: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 55rem) {
|
@media (max-width: 55rem) {
|
||||||
#voice-call-popup {
|
#voice-call-popup {
|
||||||
width: 16rem;
|
width: 16rem;
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
const CLIENT_VERSION = "0.1.2";
|
const CLIENT_VERSION = "0.1.4";
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "Miarven",
|
"name": "Miarven",
|
||||||
"version": "0.1.2",
|
"version": "0.1.4",
|
||||||
"description": "An Amazing Capacitor App",
|
"description": "An Amazing Capacitor App",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "",
|
"name": "",
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
node_modules/@capacitor/android/capacitor/build/outputs/aar/capacitor-android-release.aar
generated
vendored
BIN
node_modules/@capacitor/android/capacitor/build/outputs/aar/capacitor-android-release.aar
generated
vendored
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -1,9 +1,9 @@
|
||||||
<libraries>
|
<libraries>
|
||||||
<library
|
<library
|
||||||
name=":@@:capacitor-android::release"
|
name=":@@:capacitor-android::release"
|
||||||
jars="/home/olcxja/.gradle/caches/8.14.3/transforms/7687406e09940ba1a8559cc8a3590167/transformed/out/jars/classes.jar:/home/olcxja/.gradle/caches/8.14.3/transforms/7687406e09940ba1a8559cc8a3590167/transformed/out/jars/libs/R.jar"
|
jars="/home/olcxja/.gradle/caches/8.14.3/transforms/a60990329a178b65acb9987d031670ff/transformed/out/jars/classes.jar:/home/olcxja/.gradle/caches/8.14.3/transforms/a60990329a178b65acb9987d031670ff/transformed/out/jars/libs/R.jar"
|
||||||
resolved="android:capacitor-android:unspecified"
|
resolved="android:capacitor-android:unspecified"
|
||||||
folder="/home/olcxja/.gradle/caches/8.14.3/transforms/7687406e09940ba1a8559cc8a3590167/transformed/out"
|
folder="/home/olcxja/.gradle/caches/8.14.3/transforms/a60990329a178b65acb9987d031670ff/transformed/out"
|
||||||
manifest="AndroidManifest.xml"
|
manifest="AndroidManifest.xml"
|
||||||
resFolder="res"
|
resFolder="res"
|
||||||
assetsFolder="assets"
|
assetsFolder="assets"
|
||||||
|
|
|
||||||
Binary file not shown.
BIN
node_modules/@capacitor/app/android/build/intermediates/local_aar_for_lint/release/out.aar
generated
vendored
BIN
node_modules/@capacitor/app/android/build/intermediates/local_aar_for_lint/release/out.aar
generated
vendored
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
node_modules/@capacitor/app/android/build/outputs/aar/capacitor-app-release.aar
generated
vendored
BIN
node_modules/@capacitor/app/android/build/outputs/aar/capacitor-app-release.aar
generated
vendored
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -1,9 +1,9 @@
|
||||||
<libraries>
|
<libraries>
|
||||||
<library
|
<library
|
||||||
name=":@@:capacitor-android::release"
|
name=":@@:capacitor-android::release"
|
||||||
jars="/home/olcxja/.gradle/caches/8.14.3/transforms/7687406e09940ba1a8559cc8a3590167/transformed/out/jars/classes.jar:/home/olcxja/.gradle/caches/8.14.3/transforms/7687406e09940ba1a8559cc8a3590167/transformed/out/jars/libs/R.jar"
|
jars="/home/olcxja/.gradle/caches/8.14.3/transforms/a60990329a178b65acb9987d031670ff/transformed/out/jars/classes.jar:/home/olcxja/.gradle/caches/8.14.3/transforms/a60990329a178b65acb9987d031670ff/transformed/out/jars/libs/R.jar"
|
||||||
resolved="android:capacitor-android:unspecified"
|
resolved="android:capacitor-android:unspecified"
|
||||||
folder="/home/olcxja/.gradle/caches/8.14.3/transforms/7687406e09940ba1a8559cc8a3590167/transformed/out"
|
folder="/home/olcxja/.gradle/caches/8.14.3/transforms/a60990329a178b65acb9987d031670ff/transformed/out"
|
||||||
manifest="AndroidManifest.xml"
|
manifest="AndroidManifest.xml"
|
||||||
resFolder="res"
|
resFolder="res"
|
||||||
assetsFolder="assets"
|
assetsFolder="assets"
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "olcxja.miarven",
|
"name": "olcxja.miarven",
|
||||||
"version": "0.1.2",
|
"version": "0.1.4",
|
||||||
"description": "Larpix client",
|
"description": "Larpix client",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"author": "olcxja's softworks",
|
"author": "olcxja's softworks",
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"versionCode": 3,
|
"versionCode": 5,
|
||||||
"versionName": "0.1.2",
|
"versionName": "0.1.4",
|
||||||
"npmVersion": "0.1.2"
|
"npmVersion": "0.1.4"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -310,5 +310,19 @@
|
||||||
"error.call.screen": "screen share error: {0} :c",
|
"error.call.screen": "screen share error: {0} :c",
|
||||||
"error.call.screen.unsupported": "ur browser doesn't support screen sharing :c",
|
"error.call.screen.unsupported": "ur browser doesn't support screen sharing :c",
|
||||||
"label.stream.cam": "cam",
|
"label.stream.cam": "cam",
|
||||||
"label.stream.screen": "screen"
|
"label.stream.screen": "screen",
|
||||||
|
"action.call.settings": "voice settings :3",
|
||||||
|
"label.voice.microphone": "microphone",
|
||||||
|
"label.voice.speaker": "speaker",
|
||||||
|
"label.voice.camera": "camera",
|
||||||
|
"label.voice.camera.quality": "camera quality",
|
||||||
|
"label.voice.camera.fps": "camera fps",
|
||||||
|
"label.voice.screen.quality": "screen quality",
|
||||||
|
"label.voice.screen.fps": "screen fps",
|
||||||
|
"label.voice.sensitivity": "input sensitivity",
|
||||||
|
"label.voice.default": "default",
|
||||||
|
"error.call.microphone": "microphone error :c",
|
||||||
|
"error.voice.reconnect.failed": "voice connection lost :c",
|
||||||
|
"error.voice.ticket.rejected": "voice auth failed :c check VOICE_KEY/server version",
|
||||||
|
"error.voice.not.configured": "voice server not configured :c missing VOICE_KEY"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -319,5 +319,19 @@
|
||||||
"error.call.screen": "Screen share error: {0}",
|
"error.call.screen": "Screen share error: {0}",
|
||||||
"error.call.screen.unsupported": "Screen sharing is not supported on this browser.",
|
"error.call.screen.unsupported": "Screen sharing is not supported on this browser.",
|
||||||
"label.stream.cam": "Cam",
|
"label.stream.cam": "Cam",
|
||||||
"label.stream.screen": "Screen"
|
"label.stream.screen": "Screen",
|
||||||
|
"action.call.settings": "Voice settings",
|
||||||
|
"label.voice.microphone": "Microphone",
|
||||||
|
"label.voice.speaker": "Speaker",
|
||||||
|
"label.voice.camera": "Camera",
|
||||||
|
"label.voice.camera.quality": "Camera quality",
|
||||||
|
"label.voice.camera.fps": "Camera FPS",
|
||||||
|
"label.voice.screen.quality": "Screenshare quality",
|
||||||
|
"label.voice.screen.fps": "Screenshare FPS",
|
||||||
|
"label.voice.sensitivity": "Input sensitivity",
|
||||||
|
"label.voice.default": "Default",
|
||||||
|
"error.call.microphone": "Microphone error",
|
||||||
|
"error.voice.reconnect.failed": "Voice connection lost",
|
||||||
|
"error.voice.ticket.rejected": "Voice authentication failed - check VOICE_KEY/server version",
|
||||||
|
"error.voice.not.configured": "Voice server is not configured (missing VOICE_KEY)"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -319,5 +319,19 @@
|
||||||
"error.call.screen": "Błąd udostępniania ekranu: {0}",
|
"error.call.screen": "Błąd udostępniania ekranu: {0}",
|
||||||
"error.call.screen.unsupported": "Udostępnianie ekranu nie jest obsługiwane w tej przeglądarce.",
|
"error.call.screen.unsupported": "Udostępnianie ekranu nie jest obsługiwane w tej przeglądarce.",
|
||||||
"label.stream.cam": "Kamera",
|
"label.stream.cam": "Kamera",
|
||||||
"label.stream.screen": "Ekran"
|
"label.stream.screen": "Ekran",
|
||||||
|
"action.call.settings": "Ustawienia rozmowy",
|
||||||
|
"label.voice.microphone": "Mikrofon",
|
||||||
|
"label.voice.speaker": "Głośnik",
|
||||||
|
"label.voice.camera": "Kamera",
|
||||||
|
"label.voice.camera.quality": "Jakość kamery",
|
||||||
|
"label.voice.camera.fps": "FPS kamery",
|
||||||
|
"label.voice.screen.quality": "Jakość ekranu",
|
||||||
|
"label.voice.screen.fps": "FPS ekranu",
|
||||||
|
"label.voice.sensitivity": "Czułość wejścia",
|
||||||
|
"label.voice.default": "Domyślne",
|
||||||
|
"error.call.microphone": "Błąd mikrofonu",
|
||||||
|
"error.voice.reconnect.failed": "Utracono połączenie głosowe",
|
||||||
|
"error.voice.ticket.rejected": "Autoryzacja głosu nieudana - sprawdź VOICE_KEY/wersję serwera",
|
||||||
|
"error.voice.not.configured": "Serwer głosowy nieskonfigurowany (brak VOICE_KEY)"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2472,6 +2472,7 @@ let touchEndX = 0;
|
||||||
let touchStartY = 0;
|
let touchStartY = 0;
|
||||||
let touchEndY = 0;
|
let touchEndY = 0;
|
||||||
let touchMoved = false;
|
let touchMoved = false;
|
||||||
|
let touchStartTarget = null;
|
||||||
|
|
||||||
let pressDate;
|
let pressDate;
|
||||||
|
|
||||||
|
|
@ -2479,6 +2480,7 @@ document.addEventListener('touchstart', e => {
|
||||||
touchStartX = e.changedTouches[0].screenX;
|
touchStartX = e.changedTouches[0].screenX;
|
||||||
touchStartY = e.changedTouches[0].screenY;
|
touchStartY = e.changedTouches[0].screenY;
|
||||||
touchMoved = false;
|
touchMoved = false;
|
||||||
|
touchStartTarget = e.target;
|
||||||
|
|
||||||
activeTouchButton = e.target.closest('button, input, textarea');
|
activeTouchButton = e.target.closest('button, input, textarea');
|
||||||
if (activeTouchButton) {
|
if (activeTouchButton) {
|
||||||
|
|
@ -2558,6 +2560,18 @@ document.addEventListener('contextmenu', e => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Swipes that begin inside floating layers (popups, dialogs, dropdowns -
|
||||||
|
// anything rendered with position: fixed) belong to those layers and must
|
||||||
|
// not trigger app navigation gestures.
|
||||||
|
function touchStartedInFloatingLayer() {
|
||||||
|
let el = touchStartTarget;
|
||||||
|
while (el && el !== document.body && el !== document.documentElement) {
|
||||||
|
if (getComputedStyle(el).position === 'fixed') return true;
|
||||||
|
el = el.parentElement;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
function handleMobileSwipe() {
|
function handleMobileSwipe() {
|
||||||
const rem = parseFloat(getComputedStyle(document.documentElement).fontSize);
|
const rem = parseFloat(getComputedStyle(document.documentElement).fontSize);
|
||||||
if (window.innerWidth > 55 * rem) return;
|
if (window.innerWidth > 55 * rem) return;
|
||||||
|
|
@ -2566,6 +2580,7 @@ function handleMobileSwipe() {
|
||||||
let diffY = touchEndY - touchStartY;
|
let diffY = touchEndY - touchStartY;
|
||||||
|
|
||||||
if (Math.abs(diffX) > Math.abs(diffY) && Math.abs(diffX) > 4 * rem) {
|
if (Math.abs(diffX) > Math.abs(diffY) && Math.abs(diffX) > 4 * rem) {
|
||||||
|
if (touchStartedInFloatingLayer()) return;
|
||||||
if (diffX > 0) {
|
if (diffX > 0) {
|
||||||
mobileNavBack();
|
mobileNavBack();
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -1715,6 +1715,230 @@ input:checked + .toggle-slider:before {
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* In-call Voice Device Settings Popup */
|
||||||
|
#voice-device-settings {
|
||||||
|
position: fixed;
|
||||||
|
/* left/top are set from JS (centered, viewport-clamped) so the opening
|
||||||
|
animation cannot shift the popup and the header can drag it directly */
|
||||||
|
width: min(24rem, calc(100vw - 2rem));
|
||||||
|
max-height: calc(100vh - 3rem);
|
||||||
|
background: var(--main-bg-color);
|
||||||
|
border: var(--border-width) solid var(--light-border-color);
|
||||||
|
border-radius: 0.9rem;
|
||||||
|
box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.5);
|
||||||
|
z-index: 10020;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
|
opacity: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
transform: scale(0.92);
|
||||||
|
transition:
|
||||||
|
opacity 0.15s ease,
|
||||||
|
transform 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||||
|
}
|
||||||
|
#voice-device-settings.show {
|
||||||
|
opacity: 1;
|
||||||
|
pointer-events: auto;
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
#vds-header {
|
||||||
|
height: 2.8rem;
|
||||||
|
flex-shrink: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 0 0.6rem 0 0.9375rem;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
background: rgba(255, 255, 255, 0.03);
|
||||||
|
border-bottom: var(--border-width) solid var(--light-border-color);
|
||||||
|
user-select: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
cursor: grab;
|
||||||
|
touch-action: none;
|
||||||
|
}
|
||||||
|
#vds-header:active {
|
||||||
|
cursor: grabbing;
|
||||||
|
}
|
||||||
|
#vds-header span {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
#vds-header svg {
|
||||||
|
pointer-events: none !important;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
#vds-close {
|
||||||
|
width: 2rem;
|
||||||
|
height: 2rem;
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
color: var(--darker-text-color);
|
||||||
|
border-radius: 0.6rem;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
#vds-close:hover {
|
||||||
|
background: rgba(255, 255, 255, 0.08);
|
||||||
|
color: var(--text-color);
|
||||||
|
}
|
||||||
|
#vds-body {
|
||||||
|
padding: 0.4rem 0.7rem 0.8rem;
|
||||||
|
overflow-y: auto;
|
||||||
|
touch-action: pan-y;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.15rem;
|
||||||
|
}
|
||||||
|
.vds-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.3rem;
|
||||||
|
padding: 0.3rem 0.1rem;
|
||||||
|
}
|
||||||
|
.vds-row > label {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--darker-text-color);
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
.vds-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 0.5rem;
|
||||||
|
padding: 0.3rem 0.1rem;
|
||||||
|
}
|
||||||
|
.vds-cell {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.3rem;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
.vds-cell > label {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--darker-text-color);
|
||||||
|
}
|
||||||
|
#voice-device-settings .custom-select {
|
||||||
|
margin: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 2.3rem;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Floating option layer for the settings selects - lives on <body>, so it can
|
||||||
|
escape the popup bounds and is unaffected by the popup transform/scrolling.
|
||||||
|
Explicit solid background: never translucent over call content. */
|
||||||
|
.custom-select-options.vds-floating {
|
||||||
|
position: fixed;
|
||||||
|
display: block;
|
||||||
|
width: auto;
|
||||||
|
margin: 0;
|
||||||
|
background-color: var(--main-bg-color);
|
||||||
|
z-index: 10040;
|
||||||
|
opacity: 0;
|
||||||
|
visibility: hidden;
|
||||||
|
pointer-events: none;
|
||||||
|
transform: translateY(-0.4rem);
|
||||||
|
transition:
|
||||||
|
opacity 0.15s ease,
|
||||||
|
transform 0.15s ease,
|
||||||
|
visibility 0.15s;
|
||||||
|
}
|
||||||
|
.custom-select-options.vds-floating.vds-open {
|
||||||
|
opacity: 1;
|
||||||
|
visibility: visible;
|
||||||
|
pointer-events: auto;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
.vds-sens-meter {
|
||||||
|
position: relative;
|
||||||
|
height: 1.9rem;
|
||||||
|
background: rgba(255, 255, 255, 0.06);
|
||||||
|
border-radius: 0.55rem;
|
||||||
|
overflow: hidden;
|
||||||
|
border: var(--border-width) solid var(--light-border-color);
|
||||||
|
}
|
||||||
|
.vds-sens-fill {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
height: 100%;
|
||||||
|
width: 0%;
|
||||||
|
background: rgba(255, 255, 255, 0.15);
|
||||||
|
transition: width 0.05s linear, background-color 0.2s;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
.vds-sens-mark {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
width: 2px;
|
||||||
|
margin-left: -1px;
|
||||||
|
background: rgba(255, 255, 255, 0.65);
|
||||||
|
border-radius: 1px;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
/* Settings button keeps its hover look while the settings popup is open */
|
||||||
|
#voice-btn-settings.active {
|
||||||
|
background: rgba(255, 255, 255, 0.1);
|
||||||
|
}
|
||||||
|
#vds-sens-slider {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
margin: 0;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
background: transparent;
|
||||||
|
outline: none;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 0.55rem;
|
||||||
|
/* pan-y on the popup body would eat horizontal touch drags */
|
||||||
|
touch-action: none;
|
||||||
|
z-index: 2;
|
||||||
|
cursor: ew-resize;
|
||||||
|
}
|
||||||
|
/* The app-wide `input:active` press effect must not shrink this slider. */
|
||||||
|
#vds-sens-slider:active,
|
||||||
|
#vds-sens-slider.is-pressed {
|
||||||
|
transform: none !important;
|
||||||
|
}
|
||||||
|
#vds-sens-slider::-webkit-slider-thumb {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
width: 0.25rem;
|
||||||
|
height: 100%;
|
||||||
|
background: var(--text-color);
|
||||||
|
border-radius: 0.125rem;
|
||||||
|
box-shadow: 0 0 0.3rem rgba(0, 0, 0, 0.8);
|
||||||
|
}
|
||||||
|
#vds-sens-slider::-webkit-slider-thumb:hover,
|
||||||
|
#vds-sens-slider::-webkit-slider-thumb:active {
|
||||||
|
transform: none !important;
|
||||||
|
}
|
||||||
|
#vds-sens-slider::-moz-range-thumb {
|
||||||
|
width: 0.25rem;
|
||||||
|
height: 100%;
|
||||||
|
background: var(--text-color);
|
||||||
|
border: none;
|
||||||
|
border-radius: 0.125rem;
|
||||||
|
}
|
||||||
|
#vds-sens-slider::-moz-range-thumb:hover,
|
||||||
|
#vds-sens-slider::-moz-range-thumb:active {
|
||||||
|
transform: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 55rem) {
|
@media (max-width: 55rem) {
|
||||||
#voice-call-popup {
|
#voice-call-popup {
|
||||||
width: 16rem;
|
width: 16rem;
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
const CLIENT_VERSION = "0.1.2";
|
const CLIENT_VERSION = "0.1.4";
|
||||||
|
|
|
||||||
886
webroot/voice.js
886
webroot/voice.js
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue