From 2742d6edb012d24230a27e4e59802eb5b0c3cd7a Mon Sep 17 00:00:00 2001 From: Natsumi Date: Thu, 30 May 2024 08:56:00 +1200 Subject: [PATCH] Mobile icon, zoom, profilePicOverrideThumbnail --- html/src/app.js | 126 +++++++++++++++++----------- html/src/app.scss | 21 +++++ html/src/index.pug | 14 ++-- html/src/localization/en/en.json | 1 + html/src/masks/phone.svg | 10 +++ html/src/masks/usercutoutmobile.svg | 11 +++ html/src/mixins/tabs/settings.pug | 3 + html/src/theme.dark.scss | 14 ++++ html/src/theme.material3.scss | 62 ++++++++++---- html/src/theme.pink.scss | 19 ++++- html/src/vr.js | 31 +++---- html/src/vr.scss | 7 +- 12 files changed, 227 insertions(+), 92 deletions(-) create mode 100644 html/src/masks/phone.svg create mode 100644 html/src/masks/usercutoutmobile.svg diff --git a/html/src/app.js b/html/src/app.js index 0a12eaaa..221e597c 100644 --- a/html/src/app.js +++ b/html/src/app.js @@ -75,6 +75,13 @@ speechSynthesis.getVoices(); $app.screenshotMetadataCarouselChange(carouselNavigation); } }); + + addEventListener('wheel', (event) => { + if (event.ctrlKey) { + $app.getZoomLevel(); + } + }); + // #endregion // #region | Init: Define VRCX database helper functions, flush timer @@ -1435,8 +1442,10 @@ speechSynthesis.getVoices(); last_mobile: json.last_mobile, last_platform: json.last_platform, // location - missing from currentUser + // platform - missing from currentUser // note - missing from currentUser profilePicOverride: json.profilePicOverride, + // profilePicOverrideThumbnail - missing from currentUser pronouns: json.pronouns, state: json.state, status: json.status, @@ -1937,8 +1946,10 @@ speechSynthesis.getVoices(); last_mobile: null, last_platform: '', location: '', + platform: '', note: '', profilePicOverride: '', + profilePicOverrideThumbnail: '', pronouns: '', state: '', status: '', @@ -5504,6 +5515,7 @@ speechSynthesis.getVoices(); watch: {}, el: '#x-app', async mounted() { + await this.initLanguage(); await this.changeThemeMode(); await AppApi.SetUserAgent(); this.appVersion = await AppApi.GetVersion(); @@ -9688,56 +9700,60 @@ speechSynthesis.getVoices(); $app.methods.userStatusClass = function (user, pendingOffline) { var style = {}; - if (typeof user !== 'undefined') { - var id = ''; - if (user.id) { - id = user.id; - } else if (user.userId) { - id = user.userId; - } - if (id === API.currentUser.id) { - return this.statusClass(user.status); - } - if (!user.isFriend) { - return style; - } - if (pendingOffline) { - // Pending offline - style.offline = true; - } else if ( - user.status !== 'active' && - user.location === 'private' && - user.state === '' && - id && - !API.currentUser.onlineFriends.includes(id) - ) { - // temp fix - if (API.currentUser.activeFriends.includes(id)) { - // Active - style.active = true; - } else { - // Offline - style.offline = true; - } - } else if (user.state === 'active') { + if (typeof user === 'undefined') { + return style; + } + var id = ''; + if (user.id) { + id = user.id; + } else if (user.userId) { + id = user.userId; + } + if (id === API.currentUser.id) { + return this.statusClass(user.status); + } + if (!user.isFriend) { + return style; + } + if (pendingOffline) { + // Pending offline + style.offline = true; + } else if ( + user.status !== 'active' && + user.location === 'private' && + user.state === '' && + id && + !API.currentUser.onlineFriends.includes(id) + ) { + // temp fix + if (API.currentUser.activeFriends.includes(id)) { // Active style.active = true; - } else if (user.location === 'offline') { + } else { // Offline style.offline = true; - } else if (user.status === 'active') { - // Online - style.online = true; - } else if (user.status === 'join me') { - // Join Me - style.joinme = true; - } else if (user.status === 'ask me') { - // Ask Me - style.askme = true; - } else if (user.status === 'busy') { - // Do Not Disturb - style.busy = true; } + } else if (user.state === 'active') { + // Active + style.active = true; + } else if (user.location === 'offline') { + // Offline + style.offline = true; + } else if (user.status === 'active') { + // Online + style.online = true; + } else if (user.status === 'join me') { + // Join Me + style.joinme = true; + } else if (user.status === 'ask me') { + // Ask Me + style.askme = true; + } else if (user.status === 'busy') { + // Do Not Disturb + style.busy = true; + } + if (user.last_platform && user.last_platform !== 'standalonewindows') { + style.mobile = true; } return style; }; @@ -25616,6 +25632,9 @@ speechSynthesis.getVoices(); if (this.displayVRCPlusIconsAsAvatar && user.userIcon) { return user.userIcon; } + if (user.profilePicOverrideThumbnail) { + return user.profilePicOverrideThumbnail; + } if (user.profilePicOverride) { return user.profilePicOverride; } @@ -30915,26 +30934,25 @@ speechSynthesis.getVoices(); $app.data.appLanguage = (await configRepository.getString('VRCX_appLanguage')) ?? 'en'; i18n.locale = $app.data.appLanguage; - var initLanguage = async () => { + $app.methods.initLanguage = async function () { if (!(await configRepository.getString('VRCX_appLanguage'))) { var result = await AppApi.CurrentLanguage(); if (!result) { console.error('Failed to get current language'); - $app.changeAppLanguage('en'); + this.changeAppLanguage('en'); return; } var lang = result.split('-')[0]; i18n.availableLocales.forEach((ref) => { var refLang = ref.split('_')[0]; if (refLang === lang) { - $app.changeAppLanguage(ref); + this.changeAppLanguage(ref); } }); } $app.applyLanguageStrings(); }; - initLanguage(); $app.methods.changeAppLanguage = function (language) { console.log('Language changed:', language); @@ -32473,6 +32491,16 @@ speechSynthesis.getVoices(); // #endregion + $app.data.zoomLevel = ((await AppApi.GetZoom()) + 10) * 10; + + $app.methods.getZoomLevel = async function () { + this.zoomLevel = ((await AppApi.GetZoom()) + 10) * 10; + }; + + $app.methods.setZoomLevel = function () { + AppApi.SetZoom(this.zoomLevel / 10 - 10); + }; + $app = new Vue($app); window.$app = $app; })(); diff --git a/html/src/app.scss b/html/src/app.scss index ab2909b7..fb047a97 100644 --- a/html/src/app.scss +++ b/html/src/app.scss @@ -407,6 +407,27 @@ img.friends-list-avatar { filter: none; } +.x-friend-item > .avatar.online.mobile > img, +.x-friend-item > .avatar.joinme.mobile > img, +.x-friend-item > .avatar.askme.mobile > img, +.x-friend-item > .avatar.busy.mobile > img { + mask-image: url(masks/usercutoutmobile.svg); +} + +.x-friend-item > .avatar.online.mobile::after, +.x-friend-item > .avatar.joinme.mobile::after, +.x-friend-item > .avatar.askme.mobile::after, +.x-friend-item > .avatar.busy.mobile::after { + position: absolute; + right: -2px; + bottom: 0px; + width: 14px; + height: 14px; + content: ''; + border-radius: 0px; + mask-image: url(masks/phone.svg); +} + .x-friend-item > .avatar.active > img, .x-friend-item > .avatar.online > img, .x-friend-item > .avatar.joinme > img, diff --git a/html/src/index.pug b/html/src/index.pug index b41bccb7..4cb54309 100644 --- a/html/src/index.pug +++ b/html/src/index.pug @@ -208,8 +208,10 @@ html el-dialog.x-dialog.x-user-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="userDialog" :visible.sync="userDialog.visible" :show-close="false" width="770px") div(v-loading="userDialog.loading") div(style="display:flex") - el-popover(v-if="userDialog.ref.profilePicOverride" placement="right" width="500px" trigger="click") - img.x-link(slot="reference" v-lazy="userDialog.ref.profilePicOverride" style="flex:none;height:120px;width:213.33px;border-radius:12px;object-fit:cover") + el-popover(v-if="userDialog.ref.profilePicOverrideThumbnail || userDialog.ref.profilePicOverride" placement="right" width="500px" trigger="click") + template(slot="reference") + img.x-link(v-if="userDialog.ref.profilePicOverrideThumbnail" v-lazy="userDialog.ref.profilePicOverrideThumbnail" style="flex:none;height:120px;width:213.33px;border-radius:12px;object-fit:cover") + img.x-link(v-else v-lazy="userDialog.ref.profilePicOverride" style="flex:none;height:120px;width:213.33px;border-radius:12px;object-fit:cover") img.x-link(v-lazy="userDialog.ref.profilePicOverride" style="height:400px" @click="showFullscreenImageDialog(userDialog.ref.profilePicOverride)") el-popover(v-else placement="right" width="500px" trigger="click") img.x-link(slot="reference" v-lazy="userDialog.ref.currentAvatarThumbnailImageUrl" style="flex:none;height:120px;width:160px;border-radius:12px;object-fit:cover") @@ -2031,7 +2033,7 @@ html el-radio-button(label="On") {{ $t('dialog.shared_feed_filters.on') }} template(#footer) el-button(type="small" @click="resetSharedFeedFilters") {{ $t('dialog.shared_feed_filters.reset') }} - el-button(type="primary" size="small" style="margin-left:10px" @click="notyFeedFiltersDialog.visible = false") {{ $t('dialog.shared_feed_filters.close') }} + el-button(size="small" style="margin-left:10px" @click="notyFeedFiltersDialog.visible = false") {{ $t('dialog.shared_feed_filters.close') }} //- dialog: wrist feed filters el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="wristFeedFiltersDialog" :visible.sync="wristFeedFiltersDialog.visible" :title="$t('dialog.shared_feed_filters.wrist')" width="550px") @@ -2280,7 +2282,7 @@ html el-radio-button(label="On") {{ $t('dialog.shared_feed_filters.on') }} template(#footer) el-button(type="small" @click="resetSharedFeedFilters") {{ $t('dialog.shared_feed_filters.reset') }} - el-button(type="primary" size="small" @click="wristFeedFiltersDialog.visible = false") {{ $t('dialog.shared_feed_filters.close') }} + el-button(size="small" @click="wristFeedFiltersDialog.visible = false") {{ $t('dialog.shared_feed_filters.close') }} //- dialog: Edit Invite Message el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="editInviteMessageDialog" :visible.sync="editInviteMessageDialog.visible" :title="$t('dialog.edit_invite_message.header')" width="400px") @@ -2493,9 +2495,9 @@ html span {{ $t('dialog.gallery_icons.emoji_animation_type') }} template(v-if="emojiAnimType") span(style="margin-right:10px") {{ $t('dialog.gallery_icons.emoji_animation_fps') }} - el-input(v-model="emojiAnimFps" :min="1" :max="64" size="small" style="width:48px;margin-right:10px") + el-input-number(size="small" v-model="emojiAnimFps" :min="1" :max="64" style="margin-right:10px;width:112px") span(style="margin-right:10px") {{ $t('dialog.gallery_icons.emoji_animation_frame_count') }} - el-input(v-model="emojiAnimFrameCount" :min="1" :max="64" size="small" style="width:48px;margin-right:10px") + el-input-number(size="small" v-model="emojiAnimFrameCount" :min="2" :max="64" style="margin-right:10px;width:112px") el-checkbox(v-model="emojiAnimLoopPingPong" style="margin-left:10px;margin-right:10px") span {{ $t('dialog.gallery_icons.emoji_loop_pingpong') }} br diff --git a/html/src/localization/en/en.json b/html/src/localization/en/en.json index 2916b852..42254583 100644 --- a/html/src/localization/en/en.json +++ b/html/src/localization/en/en.json @@ -260,6 +260,7 @@ "theme_mode_darkvanilla": "Dark Vanilla", "theme_mode_pink": "Pink", "theme_mode_material3": "Material 3", + "zoom": "Zoom", "vrcplus_profile_icons": "VRCPlus Profile Icons", "disable_tooltips": "Disable Tooltips", "disable_nicknames": "Disable Memo Nicknames", diff --git a/html/src/masks/phone.svg b/html/src/masks/phone.svg new file mode 100644 index 00000000..6edfc847 --- /dev/null +++ b/html/src/masks/phone.svg @@ -0,0 +1,10 @@ + + + + + + + diff --git a/html/src/masks/usercutoutmobile.svg b/html/src/masks/usercutoutmobile.svg new file mode 100644 index 00000000..14c70e12 --- /dev/null +++ b/html/src/masks/usercutoutmobile.svg @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/html/src/mixins/tabs/settings.pug b/html/src/mixins/tabs/settings.pug index 5bb882a4..c84bb367 100644 --- a/html/src/mixins/tabs/settings.pug +++ b/html/src/mixins/tabs/settings.pug @@ -152,6 +152,9 @@ mixin settingsTab() el-radio-button(label="darkvanilla") {{ $t('view.settings.appearance.appearance.theme_mode_darkvanilla') }} el-radio-button(label="pink") {{ $t('view.settings.appearance.appearance.theme_mode_pink') }} el-radio-button(label="material3") {{ $t('view.settings.appearance.appearance.theme_mode_material3') }} + div.options-container-item + span.name {{ $t('view.settings.appearance.appearance.zoom') }} + el-input-number(size="small" v-model="zoomLevel" @change="setZoomLevel" :precision="0" style="width:128px") div.options-container-item span.name {{ $t('view.settings.appearance.appearance.vrcplus_profile_icons') }} el-switch(v-model="displayVRCPlusIconsAsAvatar" @change="saveOpenVROption") diff --git a/html/src/theme.dark.scss b/html/src/theme.dark.scss index 7df03395..936a1da5 100644 --- a/html/src/theme.dark.scss +++ b/html/src/theme.dark.scss @@ -55,6 +55,20 @@ button { border: #555; } +.el-input-number__decrease, +.el-input-number__increase { + background: unset; + color: #fff; +} + +.el-input-number__decrease { + border-right: 1px solid #dcdfe633; +} + +.el-input-number__increase { + border-left: 1px solid #dcdfe633; +} + .el-table tr, .el-table td.el-table__cell, .el-table th.el-table__cell { diff --git a/html/src/theme.material3.scss b/html/src/theme.material3.scss index 1fba2af6..1b26f7a1 100644 --- a/html/src/theme.material3.scss +++ b/html/src/theme.material3.scss @@ -183,7 +183,9 @@ div[style*='margin: 0px 0px 10px;'] { font-weight: var(--md-sys-typescale-label-large-weight); letter-spacing: var(--md-sys-typescale-label-large-tracking); padding: 0 24px; - transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out; + transition: + background-color 0.2s ease-in-out, + color 0.2s ease-in-out; } .el-tabs--card > .el-tabs__header .el-tabs__item.is-active { @@ -227,7 +229,7 @@ div[style*='margin: 0px 0px 10px;'] { } /* Input filter */ - +.el-input-number--small, .el-input--small, .el-input__inner { height: 45px !important; @@ -303,7 +305,9 @@ input[type='number'], .el-pagination button.btn-next { position: relative; background-color: rgb(var(--md-sys-color-secondary-container)); - transition: background-color 0.1s ease-in-out, color 0.1s ease-in-out; + transition: + background-color 0.1s ease-in-out, + color 0.1s ease-in-out; } .el-pagination button:not(:disabled):hover.btn-prev::after, .el-pagination button:not(:disabled):hover.btn-next::after { @@ -397,7 +401,9 @@ input[type='number'], font-size: var(--md-sys-typescale-body-small-size); font-weight: var(--md-sys-typescale-body-small-weight); letter-spacing: var(--md-sys-typescale-body-small-tracking); - transition: height 0.1s ease-out, min-height 0.1s ease-out, + transition: + height 0.1s ease-out, + min-height 0.1s ease-out, opacity 0.1s ease-out; } .el-message-box__errormsg[style='visibility: hidden;'] { @@ -654,7 +660,9 @@ input[type='number'], border-radius: 28px; background-color: rgb(var(--md-sys-color-surface-variant)) !important; border: 2px solid rgb(var(--md-sys-color-outline)) !important; - transition: background-color 0.1s ease-in-out, border-color 0.1s ease-in-out; + transition: + background-color 0.1s ease-in-out, + border-color 0.1s ease-in-out; } /* active track */ @@ -673,9 +681,13 @@ input[type='number'], margin: 4px; background-color: rgb(var(--md-sys-color-outline)); border-radius: 28px; - transition: left 200ms cubic-bezier(0, 0.5, 0.5, 1.5), - background-color 0.1s ease-in-out, height 50ms ease-out, - width 50ms ease-out, padding 50ms ease-out, margin 50ms ease-out; + transition: + left 200ms cubic-bezier(0, 0.5, 0.5, 1.5), + background-color 0.1s ease-in-out, + height 50ms ease-out, + width 50ms ease-out, + padding 50ms ease-out, + margin 50ms ease-out; } /* active thumb */ @@ -801,7 +813,9 @@ input[type='number'], line-height: var(--md-sys-typescale-label-large-line-height); font-size: var(--md-sys-typescale-label-large-size); font-weight: var(--md-sys-typescale-label-large-weight); - transition: background-color 0.1s ease-in-out, color 0.1s ease-in-out; + transition: + background-color 0.1s ease-in-out, + color 0.1s ease-in-out; } .el-radio-group > *:first-child > .el-radio-button__inner { @@ -899,7 +913,9 @@ input[type='number'], font-weight: var(--md-sys-typescale-label-large-weight); letter-spacing: var(--md-sys-typescale-label-large-tracking); border: none; - transition: background-color 0.1s ease-in-out, color 0.1s ease-in-out; + transition: + background-color 0.1s ease-in-out, + color 0.1s ease-in-out; } .el-button.el-button--primary:not(.el-button--text).is-disabled { cursor: not-allowed; @@ -947,7 +963,9 @@ input[type='number'], font-weight: var(--md-sys-typescale-label-large-weight); letter-spacing: var(--md-sys-typescale-label-large-tracking); border: none; - transition: background-color 0.1s ease-in-out, color 0.1s ease-in-out; + transition: + background-color 0.1s ease-in-out, + color 0.1s ease-in-out; } .el-button:not(.el-button--text, .el-button--primary, .is-disabled), .el-button:not(.el-button--text, .el-button--primary, .is-disabled):hover, @@ -1018,7 +1036,9 @@ input[type='number'], font-weight: var(--md-sys-typescale-label-large-weight); letter-spacing: var(--md-sys-typescale-label-large-tracking); border: none; - transition: background-color 0.1s ease-in-out, color 0.1s ease-in-out; + transition: + background-color 0.1s ease-in-out, + color 0.1s ease-in-out; } .el-button.el-button--text:not(.el-button--primary) > i { font-size: 15px; @@ -1164,7 +1184,9 @@ img.x-link.el-popover__reference { background: var(--md-sys-color-surface-4); border: none; border-radius: 12px; - box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23); + box-shadow: + 0 3px 6px rgba(0, 0, 0, 0.16), + 0 3px 6px rgba(0, 0, 0, 0.23); } .el-popover img { @@ -1181,7 +1203,9 @@ img.x-link.el-popover__reference { font-weight: var(--md-sys-typescale-label-large-weight); letter-spacing: var(--md-sys-typescale-label-large-tracking); padding: 0 24px; - transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out; + transition: + background-color 0.2s ease-in-out, + color 0.2s ease-in-out; } .el-tabs__item:not(:last-child) { @@ -1472,7 +1496,9 @@ img.x-link.el-popover__reference { border-radius: 20px; top: -10px; transform: translate(-50%); - transition: height 0.1s ease-in-out, width 0.1s ease-in-out; + transition: + height 0.1s ease-in-out, + width 0.1s ease-in-out; } .el-slider__button:hover::after, .el-slider__button:focus::after { @@ -1526,7 +1552,9 @@ img.x-link.el-popover__reference { border: none; border-radius: 8px; background: var(--md-sys-color-surface-2); - box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23); + box-shadow: + 0 3px 6px rgba(0, 0, 0, 0.16), + 0 3px 6px rgba(0, 0, 0, 0.23); overflow: auto; max-height: 90%; } @@ -1664,8 +1692,6 @@ i.x-user-status { font-variation-settings: 'FILL' 1; } - - /* right arrow */ .el-icon-right::before { content: 'arrow_right_alt'; diff --git a/html/src/theme.pink.scss b/html/src/theme.pink.scss index befd3ca9..7e74af41 100644 --- a/html/src/theme.pink.scss +++ b/html/src/theme.pink.scss @@ -103,11 +103,15 @@ textarea { .el-dialog, .el-dropdown-menu, .el-tooltip__popper.is-dark { - box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23); + box-shadow: + 0 3px 6px rgba(0, 0, 0, 0.16), + 0 3px 6px rgba(0, 0, 0, 0.23); } .el-dropdown-menu__item, .x-friend-item { - transition: background-color ease-in-out 0.1s, color ease-in-out 0.1s; + transition: + background-color ease-in-out 0.1s, + color ease-in-out 0.1s; } .el-dropdown-menu__item:focus, .el-dropdown-menu__item:not(.is-disabled):hover { @@ -144,6 +148,17 @@ textarea { .el-textarea__inner { border: var(--lighter-border); } +.el-input-number { + background-color: var(--lighter-bg); + border: 1px solid #404040; + border-radius: 5px; +} +.el-input-number__decrease { + border-right: 1px solid #404040; +} +.el-input-number__increase { + border-left: 1px solid #404040; +} .el-dropdown-menu__item--divided { border-top: 2px solid var(--lighter-lighter-lighter-lighter-bg); } diff --git a/html/src/vr.js b/html/src/vr.js index c692f37f..174711a6 100644 --- a/html/src/vr.js +++ b/html/src/vr.js @@ -674,20 +674,21 @@ Vue.component('marquee-text', MarqueeText); $app.methods.statusClass = function (status) { var style = {}; - if (typeof status !== 'undefined') { - if (status === 'active') { - // Online - style.online = true; - } else if (status === 'join me') { - // Join Me - style.joinme = true; - } else if (status === 'ask me') { - // Ask Me - style.askme = true; - } else if (status === 'busy') { - // Do Not Disturb - style.busy = true; - } + if (typeof status === 'undefined') { + return style; + } + if (status === 'active') { + // Online + style.online = true; + } else if (status === 'join me') { + // Join Me + style.joinme = true; + } else if (status === 'ask me') { + // Ask Me + style.askme = true; + } else if (status === 'busy') { + // Do Not Disturb + style.busy = true; } return style; }; @@ -708,7 +709,7 @@ Vue.component('marquee-text', MarqueeText); text = `${worldName} ${L.accessTypeName}`; } } - return text; + return escapeTag(text); }; $app.methods.notyClear = function () { diff --git a/html/src/vr.scss b/html/src/vr.scss index 5216ebc6..82539ecf 100644 --- a/html/src/vr.scss +++ b/html/src/vr.scss @@ -318,8 +318,8 @@ button { i.x-user-status { display: inline-block; - width: 14px; - height: 14px; + width: 13px; + height: 13px; background: #808080; border-radius: 50%; } @@ -334,14 +334,17 @@ i.x-user-status.online { i.x-user-status.joinme { background: #409eff; + mask-image: url(masks/joinme.svg); } i.x-user-status.askme { background: #ff9500; + mask-image: url(masks/askme.svg); } i.x-user-status.busy { background: #ff2c2c; + mask-image: url(masks/busy.svg); } .spin {