diff --git a/html/src/app.dark.scss b/html/src/app.dark.scss index d6ceca81..14c086d9 100644 --- a/html/src/app.dark.scss +++ b/html/src/app.dark.scss @@ -362,7 +362,8 @@ button { .x-friend-item > .avatar.online::after, .x-friend-item > .avatar.joinme::after, .x-friend-item > .avatar.askme::after, -.x-friend-item > .avatar.busy::after { +.x-friend-item > .avatar.busy::after, +.x-friend-item > .avatar.offline::after { border: 2px solid #000; } diff --git a/html/src/app.js b/html/src/app.js index b2ceab06..2177f635 100644 --- a/html/src/app.js +++ b/html/src/app.js @@ -6537,6 +6537,7 @@ speechSynthesis.getVoices(); name: '', no: ++this.friendsNo, memo: '', + pendingOffline: false, $nickName: '' }; if (this.friendLogInitStatus) { @@ -6629,6 +6630,7 @@ speechSynthesis.getVoices(); } if (stateInput === 'online') { this.APILastOnline.set(id, Date.now()); + ctx.pendingOffline = false; } var ref = API.cachedUsers.get(id); var isVIP = API.cachedFavoritesByObjectId.has(id); @@ -6714,6 +6716,9 @@ speechSynthesis.getVoices(); ctx.state === 'online' && (stateInput === 'active' || stateInput === 'offline') ) { + ctx.ref = ref; + ctx.isVIP = isVIP; + ctx.name = ref.displayName; // delayed second check to prevent status flapping var date = this.updateFriendInProgress.get(id); if (date && date > Date.now() - 120000) { @@ -6728,9 +6733,11 @@ speechSynthesis.getVoices(); } return; } + ctx.pendingOffline = true; this.updateFriendInProgress.set(id, Date.now()); // wait 2minutes then check if user came back online workerTimers.setTimeout(() => { + ctx.pendingOffline = false; this.updateFriendInProgress.delete(id); this.updateFriendDelayedCheck( id, @@ -6742,6 +6749,9 @@ speechSynthesis.getVoices(); ); }, 110000); } else { + ctx.ref = ref; + ctx.isVIP = isVIP; + ctx.name = ref.displayName; this.updateFriendDelayedCheck( id, ctx, @@ -6773,7 +6783,8 @@ speechSynthesis.getVoices(); ctx.name, new Date().toJSON(), 'falsePositiveOffline', - stateInput + stateInput, + ctx.ref.state ); } return; @@ -6788,8 +6799,8 @@ speechSynthesis.getVoices(); ctx.name, new Date().toJSON(), 'updateFriendState', - newState, - stateInput + stateInput, + ctx.ref.state ); } var newRef = args.ref; @@ -7145,7 +7156,7 @@ speechSynthesis.getVoices(); return this.friendsGroup3_; }; - $app.methods.userStatusClass = function (user) { + $app.methods.userStatusClass = function (user, pendingOffline) { var style = {}; if (typeof user !== 'undefined') { var id = ''; @@ -7160,14 +7171,17 @@ speechSynthesis.getVoices(); if (!user.isFriend) { return ''; } - // temp fix - if ( + 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; diff --git a/html/src/app.scss b/html/src/app.scss index 72adecb3..3831f6f9 100644 --- a/html/src/app.scss +++ b/html/src/app.scss @@ -340,7 +340,8 @@ img.friends-list-avatar { .x-friend-item > .avatar.online::after, .x-friend-item > .avatar.joinme::after, .x-friend-item > .avatar.askme::after, -.x-friend-item > .avatar.busy::after { +.x-friend-item > .avatar.busy::after, +.x-friend-item > .avatar.offline::after { position: absolute; right: 0; bottom: 0; @@ -372,6 +373,10 @@ img.friends-list-avatar { background: #f56c6c; } +.x-friend-item > .avatar.offline::after { + background: #909399; +} + .x-friend-item.offline > .avatar::after { display: none; } diff --git a/html/src/index.pug b/html/src/index.pug index bf32a423..37867f23 100644 --- a/html/src/index.pug +++ b/html/src/index.pug @@ -1375,12 +1375,13 @@ html div(v-show="isFriendsGroup0") .x-friend-item(v-for="friend in friendsGroup0" :key="friend.id" @click="showUserDialog(friend.id)") template(v-if="friend.ref") - .avatar(:class="userStatusClass(friend.ref)") + .avatar(:class="userStatusClass(friend.ref, friend.pendingOffline)") img(v-lazy="userImage(friend.ref)") .detail span.name(v-if="friend.$nickName" :style="{'color':friend.ref.$userColour}") {{ friend.ref.displayName }} ({{ friend.$nickName }}) span.name(v-else v-text="friend.ref.displayName" :style="{'color':friend.ref.$userColour}") - location.extra(:location="friend.ref.location" :traveling="friend.ref.travelingToLocation" :link="false") + span.extra(v-if="friend.pendingOffline") #[i.el-icon-warning-outline] Pending Offline + location.extra(v-else :location="friend.ref.location" :traveling="friend.ref.travelingToLocation" :link="false") template(v-else) span(v-text="friend.name || friend.id") el-button(type="text" icon="el-icon-close" size="mini" @click.stop="confirmDeleteFriend(friend.id)" style="margin-left:5px") @@ -1390,12 +1391,13 @@ html div(v-show="isFriendsGroup1") .x-friend-item(v-for="friend in friendsGroup1" :key="friend.id" @click="showUserDialog(friend.id)") template(v-if="friend.ref") - .avatar(:class="userStatusClass(friend.ref)") + .avatar(:class="userStatusClass(friend.ref, friend.pendingOffline)") img(v-lazy="userImage(friend.ref)") .detail span.name(v-if="friend.$nickName" :style="{'color':friend.ref.$userColour}") {{ friend.ref.displayName }} ({{ friend.$nickName }}) span.name(v-else v-text="friend.ref.displayName" :style="{'color':friend.ref.$userColour}") - location.extra(:location="friend.ref.location" :traveling="friend.ref.travelingToLocation" :link="false") + span.extra(v-if="friend.pendingOffline") #[i.el-icon-warning-outline] Pending Offline + location.extra(v-else :location="friend.ref.location" :traveling="friend.ref.travelingToLocation" :link="false") template(v-else) span(v-text="friend.name || friend.id") el-button(type="text" icon="el-icon-close" size="mini" @click.stop="confirmDeleteFriend(friend.id)" style="margin-left:5px") @@ -1528,7 +1530,7 @@ html el-dropdown-item(icon="el-icon-delete" command="Unfriend" divided) Unfriend el-tabs(ref="userDialogTabs" @tab-click="userDialogTabClick") el-tab-pane(label="Info") - template(v-if="!userDialog.isFriend || isFriendOnline(userDialog.friend)") + template(v-if="isFriendOnline(userDialog.friend) || API.currentUser.id === userDialog.id") div(v-if="userDialog.ref.location" style="display:flex;flex-direction:column;margin-bottom:10px;padding-bottom:10px;border-bottom:1px solid #e4e7ed14") div(style="flex:none") location(:location="userDialog.ref.location" :traveling="userDialog.ref.travelingToLocation")