feat(vk): native share/copy, auto theme, friend-code deep link, home-bar safe area
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Has been skipped
CI / integration (pull_request) Has been skipped
CI / ui (pull_request) Successful in 55s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m25s
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Has been skipped
CI / integration (pull_request) Has been skipped
CI / ui (pull_request) Successful in 55s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m25s
Group B of the VK integration — the contour-verified follow-up to the launch+auth MVP: - Share/copy inside the VK iframe go through VK Bridge: the friend-code invite shares via VKWebAppShare and copies via VKWebAppCopyText, since navigator.share is absent in the desktop iframe and navigator.clipboard is blocked there. - The invite link is a VK Mini App direct link (vk.com/app<id>#f<code>) on VK instead of the Telegram link; the app id comes from vk_app_id in the launch params (no build arg needed). The recipient's launch routes the deep link from VK's `hash` launch query parameter. - The app's "auto" theme follows the VK client's light/dark appearance (VKWebAppUpdateConfig), which the VK mobile webview's prefers-color-scheme does not track. - The safe-area CSS vars default to env(safe-area-inset-*), so the VK mobile layout clears the home bar (and Capacitor/PWA too); Telegram still overrides them from its SDK. vk.ts adds vkAppId/vkStartParam/vkShare/vkCopyText/vkOnScheme. Verified: svelte-check, 347 unit (+ vkAppId/vkStartParam/vkShareLink), build, bundle-gate. The VK-Bridge behaviours need the live contour (not reproducible headless).
This commit is contained in:
@@ -6,8 +6,9 @@
|
||||
import { gateway } from '../lib/gateway';
|
||||
import { GatewayError } from '../lib/client';
|
||||
import { t } from '../lib/i18n/index.svelte';
|
||||
import { friendCodeParam, shareLink } from '../lib/deeplink';
|
||||
import { friendCodeParam, shareLink, vkShareLink } from '../lib/deeplink';
|
||||
import { insideTelegram, shareTelegramLink, telegramDialogsAvailable, telegramShowConfirm } from '../lib/telegram';
|
||||
import { insideVK, vkCopyText, vkShare } from '../lib/vk';
|
||||
import type { AccountRef, FriendCode, RobotBlockEntry } from '../lib/model';
|
||||
|
||||
let friends = $state<AccountRef[]>([]);
|
||||
@@ -140,6 +141,11 @@
|
||||
|
||||
async function copyCode() {
|
||||
if (!code) return;
|
||||
// Inside the VK iframe navigator.clipboard is blocked, so copy via VK Bridge there.
|
||||
if (insideVK()) {
|
||||
if (await vkCopyText(code.code)) showToast(t('friends.codeCopied'));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await navigator.clipboard.writeText(code.code);
|
||||
showToast(t('friends.codeCopied'));
|
||||
@@ -153,6 +159,13 @@
|
||||
// copies the link to the clipboard.
|
||||
async function shareInvite(url: string) {
|
||||
const text = t('friends.inviteText');
|
||||
// Inside VK navigator.share is absent (desktop iframe) and the clipboard is blocked: share via VK
|
||||
// Bridge, falling back to a VK-Bridge clipboard copy if the share is dismissed or unavailable.
|
||||
if (insideVK()) {
|
||||
if (await vkShare(url)) return;
|
||||
if (await vkCopyText(url)) showToast(t('friends.linkCopied'));
|
||||
return;
|
||||
}
|
||||
if (shareTelegramLink(url, text)) return;
|
||||
if (typeof navigator !== 'undefined' && navigator.share) {
|
||||
try {
|
||||
@@ -188,7 +201,8 @@
|
||||
<button class="btn" onclick={redeem} disabled={!connection.online}>{t('friends.redeem')}</button>
|
||||
</div>
|
||||
{#if code}
|
||||
{@const tg = shareLink(friendCodeParam(code.code))}
|
||||
{@const sharePayload = friendCodeParam(code.code)}
|
||||
{@const shareUrl = insideVK() ? vkShareLink(sharePayload) : shareLink(sharePayload)}
|
||||
<div class="code" data-testid="friend-code">
|
||||
<div class="coderow">
|
||||
<button class="codeval" onclick={copyCode}>{code.code}</button>
|
||||
@@ -197,8 +211,8 @@
|
||||
<span class="codehint">
|
||||
{t('friends.codeHint')} · {t('friends.codeExpires', { time: codeTime(code.expiresAtUnix) })}
|
||||
</span>
|
||||
{#if tg}
|
||||
<button type="button" class="link" onclick={() => shareInvite(tg)}>{t('friends.shareTelegram')}</button>
|
||||
{#if shareUrl}
|
||||
<button type="button" class="link" onclick={() => shareInvite(shareUrl)}>{t('friends.shareTelegram')}</button>
|
||||
{/if}
|
||||
</div>
|
||||
{:else}
|
||||
|
||||
Reference in New Issue
Block a user