+
);
diff --git a/src/renderer/src/scss/_variables.scss b/src/renderer/src/scss/_variables.scss
index c24a002..57567e2 100644
--- a/src/renderer/src/scss/_variables.scss
+++ b/src/renderer/src/scss/_variables.scss
@@ -23,6 +23,7 @@
rgba(208, 214, 140, 1) 100%
);
--telegram-android-bg-gradient-light: var(--telegram-ios-bg-gradient-light);
+ --telegram-desktop-bg-gradient-light: var(--telegram-ios-bg-gradient-light);
--telegram-ios-bg-gradient-dark: linear-gradient(
135deg,
diff --git a/src/renderer/src/scss/sections/_menu-more.scss b/src/renderer/src/scss/sections/_menu-more.scss
index 163f8b6..8f41e61 100644
--- a/src/renderer/src/scss/sections/_menu-more.scss
+++ b/src/renderer/src/scss/sections/_menu-more.scss
@@ -129,4 +129,48 @@
}
}
}
+
+ &.tdesktop {
+ > div {
+ border-radius: 0.5rem;
+ overflow: hidden;
+ -webkit-backdrop-filter: saturate(180%) blur(20px);
+ backdrop-filter: saturate(180%) blur(20px);
+ border: 1px solid;
+
+ > ul {
+ > li:not(:last-child) {
+ border-bottom: 1px solid;
+ }
+ }
+ }
+
+ &.light {
+ > div {
+ background-color: rgba(255, 255, 255, 0.75);
+ color: #000000;
+ border-color: rgba(0, 0, 0, 0.25);
+
+ > ul {
+ > li {
+ border-color: rgba(0, 0, 0, 0.25);
+ }
+ }
+ }
+ }
+
+ &.dark {
+ > div {
+ background-color: rgba(38, 38, 38, 0.75);
+ color: #ffffff;
+ border-color: rgba(255, 255, 255, 0.25);
+
+ > ul {
+ > li {
+ border-color: rgba(255, 255, 255, 0.25);
+ }
+ }
+ }
+ }
+ }
}
diff --git a/src/renderer/src/scss/sections/_popup.scss b/src/renderer/src/scss/sections/_popup.scss
index afa8947..2be9f69 100644
--- a/src/renderer/src/scss/sections/_popup.scss
+++ b/src/renderer/src/scss/sections/_popup.scss
@@ -212,3 +212,108 @@
}
}
}
+
+.popup-overlay.tdesktop {
+ position: absolute;
+ inset: 0;
+ z-index: 99999999;
+
+ > div {
+ position: absolute;
+ inset: 0;
+ transition: all 0.25s;
+ background-color: rgba(0, 0, 0, 0.5);
+ }
+
+ &.light {
+ > section {
+ background-color: var(--tg-var-tdesktop-light-bg_color);
+ color: #000000;
+
+ > ul {
+ > li {
+ color: rgba(0, 128, 255);
+ border-color: rgba(0, 0, 0, 0.2) !important;
+
+ &:active {
+ background-color: rgba(0, 0, 0, 0.1);
+ }
+ }
+ }
+ }
+ }
+
+ &.dark {
+ > section {
+ background-color: var(--tg-var-tdesktop-dark-bg_color);
+ color: #ffffff;
+
+ > ul {
+ > li {
+ color: var(--tg-var-tdesktop-light-button_color);
+ border-color: rgba(255, 255, 255, 0.15) !important;
+
+ &:active {
+ background-color: rgba(255, 255, 255, 0.1);
+ }
+ }
+ }
+ }
+ }
+
+ > section {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translateX(-50%) translateY(-50%);
+ border-radius: 0.75rem;
+ width: 90%;
+ overflow: hidden;
+
+ > div {
+ display: flex;
+ flex-direction: column;
+ padding: 1rem;
+
+ > b {
+ font-weight: bold;
+ font-size: 1.25rem;
+ text-align: initial;
+ width: 100%;
+ padding-bottom: 0.5rem;
+ }
+
+ > p {
+ font-size: 1rem;
+ text-align: initial;
+ width: 100%;
+ }
+ }
+
+ > ul {
+ display: flex;
+ align-items: center;
+ direction: rtl;
+ padding: 0 0.5rem 0.25rem;
+
+ > li {
+ display: flex;
+ padding: 0.5rem;
+ text-align: center;
+ justify-content: center;
+ align-items: center;
+ cursor: pointer;
+
+ > span.destructive {
+ direction: ltr;
+ color: var(--tg-var-tdesktop-light-destructive_text_color);
+ }
+
+ &:nth-child(3) {
+ flex-grow: 1;
+ justify-content: end;
+ }
+ }
+ }
+ }
+}
diff --git a/src/renderer/src/scss/sections/_viewport-desktop.scss b/src/renderer/src/scss/sections/_viewport-desktop.scss
new file mode 100644
index 0000000..7024f2c
--- /dev/null
+++ b/src/renderer/src/scss/sections/_viewport-desktop.scss
@@ -0,0 +1,306 @@
+#viewport-telegram-desktop {
+ display: flex;
+ width: 100%;
+ height: 100%;
+ flex-direction: column;
+ position: relative;
+ border-radius: 0.625rem;
+ overflow: hidden;
+ box-shadow: var(--shadow-deep);
+
+ > header {
+ display: flex;
+ padding: 1rem;
+ cursor: default;
+ gap: 1rem;
+
+ * {
+ cursor: default;
+ }
+
+ > div {
+ &:nth-child(2) {
+ display: flex;
+ align-items: center;
+
+ > span {
+ display: flex;
+ align-items: center;
+ font-size: 0.925rem;
+
+ > svg {
+ display: inline;
+ font-size: 1.425rem;
+ }
+ }
+ }
+
+ &:nth-child(1) {
+ flex-grow: 1;
+ display: flex;
+ gap: 0.75rem;
+
+ > div:first-child {
+ display: flex;
+ align-items: center;
+ justify-content: end;
+
+ > span {
+ display: flex;
+ color: white;
+ aspect-ratio: 1/1;
+ border-radius: 50%;
+ width: 2.25rem;
+ align-items: center;
+ justify-content: center;
+ text-align: center;
+ font-weight: 500;
+ }
+ }
+
+ > div:last-child {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: flex-start;
+ text-align: initial;
+ overflow: hidden;
+ max-width: 100%;
+ text-overflow: ellipsis;
+
+ > h2 {
+ line-height: normal;
+ font-size: 1rem;
+ font-weight: 600;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ overflow: hidden;
+ display: flex;
+ max-width: 12rem;
+ }
+
+ > span {
+ line-height: normal;
+ font-size: 0.75rem;
+ opacity: 0.75;
+ }
+ }
+ }
+ }
+ }
+
+ &.dark {
+ border-color: var(--tg-var-tdesktop-dark-section_separator_color);
+
+ > header {
+ border-color: var(--tg-var-tdesktop-dark-section_separator_color);
+ }
+
+ > div:nth-child(2) {
+ background: var(--tg-var-tdesktop-dark-bg_color);
+
+ &::before {
+ filter: invert(1);
+ }
+ }
+
+ > section {
+ > footer {
+ background-color: var(--tg-var-tdesktop-dark-bottom_bar_bg_color);
+ }
+ }
+ }
+
+ > div:nth-child(2) {
+ display: flex;
+ content: "";
+ flex-grow: 1;
+ background: var(--telegram-desktop-bg-gradient-light);
+ position: relative;
+
+ &::before {
+ background: url("/assets/patterns/pattern-2.svg") repeat;
+ position: absolute;
+ inset: 0;
+ width: 100%;
+ height: 100%;
+ content: "";
+ opacity: 0.125;
+ }
+ }
+
+ &.open {
+ background-color: black;
+
+ > header {
+ background-color: var(--tg-var-tdesktop-light-section_bg_color) !important;
+ }
+
+ &.dark {
+ > header {
+ background-color: var(--tg-var-tdesktop-dark-section_bg_color) !important;
+ }
+
+ > section {
+ > header {
+ border-bottom: 1px solid var(--tg-var-tdesktop-dark-section_separator_color);
+ }
+ }
+ }
+ }
+
+ > section {
+ position: absolute;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ top: auto;
+ display: flex;
+ flex-direction: column;
+ overflow: hidden;
+ height: 100%;
+
+ > header {
+ display: flex;
+ align-items: center;
+ gap: 1rem;
+ padding: 0 1rem;
+ cursor: default;
+
+ > div {
+ &:nth-child(1) {
+ display: flex;
+ align-items: center;
+
+ > span {
+ display: flex;
+ align-items: center;
+ font-size: 1.375rem;
+ cursor: pointer;
+ }
+ }
+
+ &:nth-child(2) {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: flex-start;
+ text-align: initial;
+ overflow: hidden;
+ max-width: 100%;
+ text-overflow: ellipsis;
+ flex-grow: 1;
+ margin-inline-start: -0.325rem;
+ padding: 1.25rem 0;
+
+ > h2 {
+ line-height: normal;
+ font-size: 1.175rem;
+ font-weight: 600;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ overflow: hidden;
+ display: flex;
+ max-width: 100%;
+ }
+ }
+
+ &:nth-child(3),
+ &:nth-child(4) {
+ display: flex;
+ align-items: center;
+ justify-content: end;
+ font-size: 1.375rem;
+ cursor: pointer;
+ }
+ }
+ }
+
+ > section {
+ display: flex;
+ flex-direction: column;
+ padding: 0;
+ margin: 0;
+ flex-grow: 1;
+ position: relative;
+
+ > div {
+ position: absolute;
+ inset: 0;
+ z-index: 999999;
+ }
+
+ > webview {
+ display: flex;
+ padding: 0;
+ margin: 0;
+ flex-grow: 1;
+ width: 100%;
+ height: 100%;
+ }
+ }
+
+ > footer {
+ background-color: var(--tg-var-tdesktop-light-bottom_bar_bg_color);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ text-align: center;
+ padding: 1rem;
+
+ > span {
+ color: var(--tg-var-tdesktop-light-hint_color);
+ }
+ }
+ }
+
+ > footer {
+ position: absolute;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ top: auto;
+ display: flex;
+ padding: 0.75rem 1rem 1.75rem;
+ gap: 0.5rem;
+ align-items: center;
+
+ > button {
+ cursor: pointer;
+ line-height: normal;
+ padding: 0 0.625rem;
+ border-radius: 100rem;
+ font-size: 0.875rem;
+ display: flex;
+ gap: 0.25rem;
+ align-items: center;
+ height: 2rem;
+
+ > svg {
+ font-size: 1.125rem;
+ }
+ }
+
+ > div {
+ display: flex;
+ flex-grow: 1;
+ align-items: center;
+ border-radius: 100rem;
+ padding: 0.25rem 0.75rem;
+
+ > span {
+ flex-grow: 1;
+ }
+ }
+
+ svg {
+ font-size: 1.325rem;
+ }
+ }
+
+ #section-telegram-bottombar {
+ > ul {
+ padding: 1rem;
+ }
+ }
+}
diff --git a/src/renderer/src/scss/sections/_viewport-ios.scss b/src/renderer/src/scss/sections/_viewport-ios.scss
index 8d9e2b0..950b9b6 100644
--- a/src/renderer/src/scss/sections/_viewport-ios.scss
+++ b/src/renderer/src/scss/sections/_viewport-ios.scss
@@ -106,7 +106,7 @@
position: relative;
&::before {
- background: url("/assets/patterns/pattern-1.svg") repeat;
+ background: url("/assets/patterns/pattern-3.svg") repeat;
position: absolute;
inset: 0;
width: 100%;
diff --git a/src/renderer/src/sections/HeaderWidget.tsx b/src/renderer/src/sections/HeaderWidget.tsx
index 26eedf4..bec5e7d 100644
--- a/src/renderer/src/sections/HeaderWidget.tsx
+++ b/src/renderer/src/sections/HeaderWidget.tsx
@@ -109,22 +109,24 @@ export const HeaderWidget: Component<{
-
-
- setProjectFrame("state", "expanded", checked)
- }
- >
- {(checked) => (
- }>
-
-
- )}
-
-
+
+
+
+ setProjectFrame("state", "expanded", checked)
+ }
+ >
+ {(checked) => (
+ }>
+
+
+ )}
+
+
+
diff --git a/src/renderer/src/sections/MenuMore.tsx b/src/renderer/src/sections/MenuMore.tsx
index 9ab9242..6d95f26 100644
--- a/src/renderer/src/sections/MenuMore.tsx
+++ b/src/renderer/src/sections/MenuMore.tsx
@@ -63,6 +63,10 @@ export const MenuMore: Component<{
setMenuMore("open", !menuMore.open)} />
+
+
+ setMenuMore("open", !menuMore.open)} />
+
diff --git a/src/renderer/src/sections/TMAView.tsx b/src/renderer/src/sections/TMAView.tsx
index 78686d3..336f760 100644
--- a/src/renderer/src/sections/TMAView.tsx
+++ b/src/renderer/src/sections/TMAView.tsx
@@ -32,6 +32,7 @@ import type {
import type { WebviewTag } from "electron";
import type { MenuMoreStore } from "./MenuMore";
import { preferences } from "@renderer/utils/preferences";
+import { sleep } from "telegram/Helpers";
declare module "solid-js" {
namespace JSX {
@@ -96,8 +97,12 @@ export const TMAView: Component<{
tgEmitEvent(
"viewport_changed",
{
- height: Math.round(height),
- width: Math.round(width),
+ height: Math.round(
+ height / (width / preferences.viewport[projectFrame.platform]),
+ ),
+ width: Math.round(
+ width / (width / preferences.viewport[projectFrame.platform]),
+ ),
is_expanded: projectFrame.state.expanded,
is_state_stable: true,
},
@@ -359,7 +364,10 @@ export const TMAView: Component<{
if (!projectFrame.state.open) {
batch(() => {
setProjectFrame("inspectElement", "open", false);
- setProjectFrame("state", "expanded", false);
+
+ if (["android", "ios"].includes(projectFrame.platform)) {
+ setProjectFrame("state", "expanded", false);
+ }
setProjectInner("backButton", "enabled", false);
setProjectInner("settingsButton", "enabled", false);
@@ -409,16 +417,27 @@ export const TMAView: Component<{
});
projectInner.webview.addEventListener("dom-ready", () => {
- projectInner.webview?.insertCSS(webviewStyle);
+ if (["android", "ios"].includes(projectFrame.platform)) {
+ projectInner.webview?.insertCSS(webviewStyle);
+ }
setProjectInner("ready", true);
});
- projectInner.webview.addEventListener("did-stop-loading", () => {
- projectInner.webview?.setZoomFactor(
- projectInner.webview?.clientWidth /
- preferences.viewport[projectFrame.platform],
- );
- });
+ const handleZoomEvent = async () => {
+ const setZoom = () => {
+ projectInner.webview?.setZoomFactor(
+ projectInner.webview?.clientWidth /
+ preferences.viewport[projectFrame.platform],
+ );
+ };
+
+ for (let i = 0; i <= 10; i++) {
+ setZoom();
+ await sleep(10);
+ }
+ };
+
+ projectInner.webview.addEventListener("did-stop-loading", handleZoomEvent);
onCleanup(() => {
if (projectFrame.state.open && projectInner.webview?.isDevToolsOpened()) {
diff --git a/src/renderer/src/sections/ViewportDesktop.tsx b/src/renderer/src/sections/ViewportDesktop.tsx
new file mode 100644
index 0000000..b4e00b0
--- /dev/null
+++ b/src/renderer/src/sections/ViewportDesktop.tsx
@@ -0,0 +1,293 @@
+import "../scss/sections/_viewport-desktop.scss";
+
+import { DesktopFrame } from "@renderer/components/DeviceFrames";
+import type { Project } from "@renderer/types";
+import { stringToColorDark, getNameInitials } from "@renderer/utils/general";
+import {
+ generateProjectInner,
+ generateProjectMenuMore,
+ type TMAProjectInner,
+} from "@renderer/utils/telegram";
+import { TelegramThemes } from "@renderer/utils/themes";
+
+import { type Component, Show } from "solid-js";
+import { BottomBar } from "./BottomBar";
+import { RiEditorAttachment2, RiSystemCloseFill } from "solid-icons/ri";
+import { TbSticker } from "solid-icons/tb";
+import { TiMicrophoneOutline } from "solid-icons/ti";
+import { BiRegularWindow } from "solid-icons/bi";
+
+import { createStore, type SetStoreFunction } from "solid-js/store";
+import { MenuMore, type MenuMoreStore } from "./MenuMore";
+import { IoArrowBackOutline } from "solid-icons/io";
+import { FiMoreVertical } from "solid-icons/fi";
+import type { TMAProjectFrame } from "@renderer/pages/Project";
+import { TMAView, TMAViewOverlay } from "./TMAView";
+
+export const ViewportDesktop: Component<{
+ project: Project;
+ projectFrameStore: [TMAProjectFrame, SetStoreFunction
];
+ placeholder: boolean;
+}> = (props) => {
+ const [projectFrame, setProjectFrame] = props.projectFrameStore;
+ const [projectInner, setProjectInner] = createStore(
+ generateProjectInner(projectFrame),
+ );
+ const [menuMore, setMenuMore] = createStore(
+ generateProjectMenuMore(),
+ );
+
+ setProjectFrame("state", "expanded", true);
+
+ return (
+
+
+
+
+
+
+
+
+
+
+ Message
+
+
+
+
+ }
+ >
+
+
+
+
+
+
+
+ setMenuMore("closeOrBack", "clicked", true)
+ }
+ >
+
+
+
+
+
+
{props.project.name}
+
+
+
+
+ setProjectFrame("state", "open", false)}
+ >
+
+
+
+
+
+
+
+ {props.project.name}
+
+ }
+ >
+
+
+
+
+
+
+
+
+
+ );
+};
diff --git a/src/renderer/src/utils/general.ts b/src/renderer/src/utils/general.ts
index d9ceaf8..899be33 100644
--- a/src/renderer/src/utils/general.ts
+++ b/src/renderer/src/utils/general.ts
@@ -85,3 +85,7 @@ export const isValidURL = (url) => {
validator.isURL(url, { host_whitelist: ["localhost"] })
);
};
+
+export const sleep = (ms: number) => {
+ return new Promise((resolve) => setTimeout(resolve, ms));
+};
diff --git a/src/renderer/src/utils/telegram.ts b/src/renderer/src/utils/telegram.ts
index 08e8211..fd986d6 100644
--- a/src/renderer/src/utils/telegram.ts
+++ b/src/renderer/src/utils/telegram.ts
@@ -343,8 +343,12 @@ export const tgEventHandler = (
tgEmitEvent(
"viewport_changed",
{
- height: Math.round(height),
- width: Math.round(width),
+ height: Math.round(
+ height / (width / preferences.viewport[projectFrame.platform]),
+ ),
+ width: Math.round(
+ width / (width / preferences.viewport[projectFrame.platform]),
+ ),
is_expanded: projectFrame.state.expanded,
is_state_stable: true,
},