People nearby [1/2]
This commit is contained in:
parent
4734ce0f1f
commit
946c516513
@ -25,6 +25,7 @@ import AppNewChannelTab from "./tabs/newChannel";
|
|||||||
import AppContactsTab from "./tabs/contacts";
|
import AppContactsTab from "./tabs/contacts";
|
||||||
import AppArchivedTab from "./tabs/archivedTab";
|
import AppArchivedTab from "./tabs/archivedTab";
|
||||||
import AppAddMembersTab from "./tabs/addMembers";
|
import AppAddMembersTab from "./tabs/addMembers";
|
||||||
|
import AppPeopleNearby from "./tabs/PeopleNearby";
|
||||||
import { i18n_, LangPackKey } from "../../lib/langPack";
|
import { i18n_, LangPackKey } from "../../lib/langPack";
|
||||||
import { ButtonMenuItemOptions } from "../buttonMenu";
|
import { ButtonMenuItemOptions } from "../buttonMenu";
|
||||||
import CheckboxField from "../checkboxField";
|
import CheckboxField from "../checkboxField";
|
||||||
@ -42,6 +43,7 @@ import { closeBtnMenu } from "../misc";
|
|||||||
import { indexOfAndSplice } from "../../helpers/array";
|
import { indexOfAndSplice } from "../../helpers/array";
|
||||||
import ButtonIcon from "../buttonIcon";
|
import ButtonIcon from "../buttonIcon";
|
||||||
import confirmationPopup from "../confirmationPopup";
|
import confirmationPopup from "../confirmationPopup";
|
||||||
|
import AppUsersManager from "../../lib/appManagers/appUsersManager";
|
||||||
|
|
||||||
export const LEFT_COLUMN_ACTIVE_CLASSNAME = 'is-left-column-shown';
|
export const LEFT_COLUMN_ACTIVE_CLASSNAME = 'is-left-column-shown';
|
||||||
|
|
||||||
@ -141,6 +143,12 @@ export class AppSidebarLeft extends SidebarSlider {
|
|||||||
icon: 'user',
|
icon: 'user',
|
||||||
text: 'Contacts',
|
text: 'Contacts',
|
||||||
onClick: onContactsClick
|
onClick: onContactsClick
|
||||||
|
}, {
|
||||||
|
icon: 'group',
|
||||||
|
text: 'PeopleNearby',
|
||||||
|
onClick: () => {
|
||||||
|
new AppPeopleNearby(this).opeddn();
|
||||||
|
}
|
||||||
}, {
|
}, {
|
||||||
icon: 'settings',
|
icon: 'settings',
|
||||||
text: 'Settings',
|
text: 'Settings',
|
||||||
|
186
src/components/sidebarLeft/tabs/PeopleNearby.ts
Normal file
186
src/components/sidebarLeft/tabs/PeopleNearby.ts
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
/*
|
||||||
|
* https://github.com/morethanwords/tweb
|
||||||
|
* Copyright (C) 2019-2021 Eduard Kuzmenko
|
||||||
|
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { SliderSuperTab } from "../../slider";
|
||||||
|
import AvatarElement from "../../avatar";
|
||||||
|
import { InputUser } from "../../../layer";
|
||||||
|
import apiManager from "../../../lib/mtproto/mtprotoworker";
|
||||||
|
import appUsersManager from "../../../lib/appManagers/appUsersManager";
|
||||||
|
import appDialogsManager from "../../../lib/appManagers/appDialogsManager";
|
||||||
|
import appImManager from "../../../lib/appManagers/appImManager";
|
||||||
|
import ButtonMenuToggle from "../../buttonMenuToggle";
|
||||||
|
import { SearchGroup } from "../../appSearch";
|
||||||
|
import Button from "../../button";
|
||||||
|
import PeerTitle from "../../peerTitle";
|
||||||
|
import lottieLoader from "../../../lib/rlottie/lottieLoader";
|
||||||
|
import PopupPeer from "../../popups/peer";
|
||||||
|
import AppNewGroupTab from "./newGroup";
|
||||||
|
import type { LazyLoadQueueIntersector } from "../../lazyLoadQueue";
|
||||||
|
//import AppMediaViewer from "../../appMediaViewerNew";
|
||||||
|
|
||||||
|
export default class AppPeopleNearby extends SliderSuperTab {
|
||||||
|
private usersCategory = new SearchGroup(true, 'contacts', true, 'people-nearby-users', false);
|
||||||
|
private groupsCategory = new SearchGroup(true, 'contacts', true, 'people-nearby-groups', false);
|
||||||
|
private latestLocationSaved: { latitude: number, longitude: number, accuracy: number };
|
||||||
|
private isLocationWatched: boolean = false;
|
||||||
|
|
||||||
|
protected lazyLoadQueue: LazyLoadQueueIntersector;
|
||||||
|
|
||||||
|
protected init() {
|
||||||
|
this.container.classList.add('peoplenearby-container');
|
||||||
|
this.setTitle('PeopleNearby');
|
||||||
|
|
||||||
|
const btnMenu = ButtonMenuToggle({}, 'bottom-left', [{
|
||||||
|
icon: 'tip',
|
||||||
|
text: 'PeopleNearby.VisibilityYes',
|
||||||
|
onClick: this.startWatching
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: 'tip',
|
||||||
|
text: 'PeopleNearby.VisibilityNo',
|
||||||
|
onClick: this.startWatching
|
||||||
|
}]);
|
||||||
|
|
||||||
|
this.header.append(btnMenu);
|
||||||
|
|
||||||
|
const locatingIcon = document.createElement('span');
|
||||||
|
locatingIcon.classList.add('tgico', 'tgico-location');
|
||||||
|
|
||||||
|
const locatingAnimation = document.createElement('div');
|
||||||
|
locatingAnimation.classList.add('locating-animation-container');
|
||||||
|
locatingAnimation.appendChild(locatingIcon);
|
||||||
|
|
||||||
|
for(let i=1; i<=4; i++){
|
||||||
|
let animatingWaves = document.createElement('div');
|
||||||
|
animatingWaves.classList.add('locating-animation-waves', 'wave-'+i);
|
||||||
|
locatingAnimation.appendChild(animatingWaves);
|
||||||
|
}
|
||||||
|
|
||||||
|
const chatsContainer = document.createElement('div');
|
||||||
|
chatsContainer.classList.add('chatlist-container');
|
||||||
|
chatsContainer.append(this.usersCategory.container);
|
||||||
|
chatsContainer.append(this.groupsCategory.container);
|
||||||
|
|
||||||
|
this.scrollable.append(locatingAnimation, chatsContainer);
|
||||||
|
}
|
||||||
|
|
||||||
|
private parseDistance(distance: number){
|
||||||
|
return (distance >= 1000 ? String(distance/1000)+' km' : String(distance)+' m');
|
||||||
|
}
|
||||||
|
|
||||||
|
public opeddn() {
|
||||||
|
const result = super.open();
|
||||||
|
result.then(() => {
|
||||||
|
navigator.geolocation.getCurrentPosition(location => {
|
||||||
|
this.latestLocationSaved = {
|
||||||
|
latitude: location.coords.latitude,
|
||||||
|
longitude: location.coords.longitude,
|
||||||
|
accuracy: location.coords.accuracy
|
||||||
|
};
|
||||||
|
|
||||||
|
appUsersManager.getLocated(
|
||||||
|
location.coords.latitude,
|
||||||
|
location.coords.longitude,
|
||||||
|
location.coords.accuracy
|
||||||
|
).then((response) => {
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
const orderedPeers = response.updates[0].peers.sort((a, b) => a.distance-b.distance);
|
||||||
|
// @ts-ignore
|
||||||
|
orderedPeers.forEach(peer => {
|
||||||
|
const isChannel = peer.peer._ == 'peerChannel';
|
||||||
|
const peerId = (isChannel ? -peer.peer.channel_id : peer.peer.user_id);
|
||||||
|
|
||||||
|
let {dialog, dom} = appDialogsManager.addDialogNew({
|
||||||
|
dialog: peerId,
|
||||||
|
container: (isChannel ? this.groupsCategory : this.usersCategory).list,
|
||||||
|
drawStatus: false,
|
||||||
|
rippleEnabled: true,
|
||||||
|
meAsSaved: true,
|
||||||
|
avatarSize: 48,
|
||||||
|
lazyLoadQueue: this.lazyLoadQueue
|
||||||
|
});
|
||||||
|
|
||||||
|
dom.lastMessageSpan.append(this.parseDistance(peer.distance));
|
||||||
|
dom.containerEl.onclick = () => appImManager.setPeer(peerId);
|
||||||
|
|
||||||
|
if(isChannel){
|
||||||
|
let participantsCount = 0;
|
||||||
|
// @ts-ignore
|
||||||
|
for(let chat of response.chats){
|
||||||
|
if(chat.id == peer.peer.channel_id){
|
||||||
|
participantsCount = chat.participants_count;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dom.lastMessageSpan.append(', '+String(participantsCount)+' members');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.usersCategory.nameEl.textContent = '';
|
||||||
|
this.usersCategory.nameEl.append('Users');
|
||||||
|
this.usersCategory.setActive();
|
||||||
|
|
||||||
|
this.groupsCategory.nameEl.textContent = '';
|
||||||
|
this.groupsCategory.nameEl.append('Groups');
|
||||||
|
this.groupsCategory.setActive();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private startWatching(){
|
||||||
|
if(!this.latestLocationSaved || this.isLocationWatched) return;
|
||||||
|
this.isLocationWatched = true;
|
||||||
|
|
||||||
|
appUsersManager.getLocated(
|
||||||
|
this.latestLocationSaved.latitude,
|
||||||
|
this.latestLocationSaved.longitude,
|
||||||
|
this.latestLocationSaved.accuracy,
|
||||||
|
true, // background parameter
|
||||||
|
3600 // self_expires parameter
|
||||||
|
);
|
||||||
|
|
||||||
|
navigator.geolocation.watchPosition(
|
||||||
|
(result) => {
|
||||||
|
const isLongitudeDifferent = result.coords.longitude != this.latestLocationSaved.longitude;
|
||||||
|
const isLatitudeDifferent = result.coords.latitude != this.latestLocationSaved.latitude;
|
||||||
|
const distanceCheck = this.calculateDistance(
|
||||||
|
result.coords.latitude, result.coords.longitude,
|
||||||
|
this.latestLocationSaved.latitude, this.latestLocationSaved.longitude
|
||||||
|
) > 100;
|
||||||
|
if((isLatitudeDifferent || isLongitudeDifferent) && distanceCheck){
|
||||||
|
appUsersManager.getLocated(
|
||||||
|
result.coords.latitude,
|
||||||
|
result.coords.longitude,
|
||||||
|
result.coords.accuracy,
|
||||||
|
true // background parameter
|
||||||
|
);
|
||||||
|
this.latestLocationSaved = {
|
||||||
|
latitude: result.coords.latitude,
|
||||||
|
longitude: result.coords.longitude,
|
||||||
|
accuracy: result.coords.accuracy
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private calculateDistance(lat1: number, long1: number, lat2: number, long2: number){
|
||||||
|
const p = 0.017453292519943295; // Math.PI/180
|
||||||
|
return (
|
||||||
|
12742 * Math.asin(
|
||||||
|
Math.sqrt(
|
||||||
|
(0.5 - Math.cos((lat2-lat1) * p)) +
|
||||||
|
(
|
||||||
|
Math.cos(lat1 * p) * Math.cos(lat2 * p)
|
||||||
|
* (1 - Math.cos((long2 - long1) * p)/2)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,7 @@
|
|||||||
const lang = {
|
const lang = {
|
||||||
|
"PeopleNearby":"PeopleNearby",
|
||||||
|
"PeopleNearby.VisibilityYes":"Make me visible",
|
||||||
|
"PeopleNearby.VisibilityNo":"Disable visibility",
|
||||||
"GrantPermissions":"Grant me permissions",
|
"GrantPermissions":"Grant me permissions",
|
||||||
"Animations": "Animations",
|
"Animations": "Animations",
|
||||||
"AttachAlbum": "Album",
|
"AttachAlbum": "Album",
|
||||||
|
@ -17,7 +17,7 @@ import cleanUsername from "../../helpers/cleanUsername";
|
|||||||
import { formatFullSentTimeRaw, tsNow } from "../../helpers/date";
|
import { formatFullSentTimeRaw, tsNow } from "../../helpers/date";
|
||||||
import { formatPhoneNumber } from "../../helpers/formatPhoneNumber";
|
import { formatPhoneNumber } from "../../helpers/formatPhoneNumber";
|
||||||
import { safeReplaceObject, isObject } from "../../helpers/object";
|
import { safeReplaceObject, isObject } from "../../helpers/object";
|
||||||
import { Chat, InputContact, InputMedia, InputPeer, InputUser, User as MTUser, UserProfilePhoto, UserStatus } from "../../layer";
|
import { Chat, InputContact, InputMedia, InputPeer, Updates, InputUser, User as MTUser, UserProfilePhoto, UserStatus, InputGeoPoint } from "../../layer";
|
||||||
import I18n, { i18n, LangPackKey } from "../langPack";
|
import I18n, { i18n, LangPackKey } from "../langPack";
|
||||||
//import apiManager from '../mtproto/apiManager';
|
//import apiManager from '../mtproto/apiManager';
|
||||||
import apiManager from '../mtproto/mtprotoworker';
|
import apiManager from '../mtproto/mtprotoworker';
|
||||||
@ -853,6 +853,32 @@ export class AppUsersManager {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getLocated(
|
||||||
|
lat: number, long: number,
|
||||||
|
accuracy_radius: number,
|
||||||
|
background: boolean = false,
|
||||||
|
self_expires: number = 0
|
||||||
|
) {
|
||||||
|
const _globalThis = this;
|
||||||
|
const geo_point = {
|
||||||
|
_: 'inputGeoPoint',
|
||||||
|
lat,
|
||||||
|
long,
|
||||||
|
accuracy_radius
|
||||||
|
} as InputGeoPoint;
|
||||||
|
|
||||||
|
return apiManager.invokeApi(
|
||||||
|
'contacts.getLocated',
|
||||||
|
{geo_point, background}
|
||||||
|
).then((result) => {
|
||||||
|
// @ts-ignore
|
||||||
|
appUsersManager.saveApiUsers(result.users);
|
||||||
|
// @ts-ignore
|
||||||
|
appChatsManager.saveApiChats(result.chats);
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/* public searchContacts(query: string, limit = 20) {
|
/* public searchContacts(query: string, limit = 20) {
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
this.getContacts(query),
|
this.getContacts(query),
|
||||||
|
@ -1365,3 +1365,71 @@ $chat-helper-size: 36px;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.locating-animation-container {
|
||||||
|
min-height: 140px;
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
& .tgico.tgico-location {
|
||||||
|
padding: 50px;
|
||||||
|
background: var(--avatar-color-bottom);
|
||||||
|
width: 140px;
|
||||||
|
height: 140px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border-radius: 50%;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
font-size: 58px;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
& .locating-animation-waves {
|
||||||
|
position: fixed;
|
||||||
|
|
||||||
|
&.wave-1,
|
||||||
|
&.wave-3 {
|
||||||
|
animation: 3s waves-animation infinite;
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
border: 5px solid white;
|
||||||
|
border-radius: 50%;
|
||||||
|
clip-path: polygon(72% 0, 100% 0, 100% 100%, 72% 100%);
|
||||||
|
margin-left: 36px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.wave-2,
|
||||||
|
&.wave-4 {
|
||||||
|
animation: 5s waves-animation infinite;
|
||||||
|
width: 66px;
|
||||||
|
height: 71px;
|
||||||
|
border: 5px solid white;
|
||||||
|
border-radius: 50%;
|
||||||
|
clip-path: polygon(72% 0, 100% 0, 100% 100%, 72% 100%);
|
||||||
|
margin-left: 51px;
|
||||||
|
margin-top: 1px;
|
||||||
|
animation-delay: 2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.wave-3 {
|
||||||
|
margin-left: -36px !important;
|
||||||
|
transform: rotateY(180deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.wave-4 {
|
||||||
|
margin-left: -51px !important;
|
||||||
|
transform: rotateY(180deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes waves-animation {
|
||||||
|
from { opacity: 100%; }
|
||||||
|
50% { opacity: 0%; }
|
||||||
|
to { opacity: 100%; }
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user