4
1
mirror of https://github.com/Qortal/qortal-ui.git synced 2025-02-11 17:55:51 +00:00

extra fixes

This commit is contained in:
PhilReact 2023-10-11 21:59:34 -05:00
parent 35b71ea311
commit 435f6b1905
9 changed files with 584 additions and 220 deletions

31
blog-test.json Normal file
View File

@ -0,0 +1,31 @@
{
"name": "Q-Blog",
"defaultFeedIndex": 0,
"feed": [
{
"id": "post-creation",
"version": 1,
"updated": 1696646223261,
"title": "Q-Blog Post creations",
"description": "blablabla",
"search": {
"query": "-post-",
"identifier": "q-blog-",
"service": "BLOG_POST",
"exactmatchnames": true
},
"click": "qortal://APP/Q-Blog/$${resource.name}$$/$${customParams.blogId}$$/$${customParams.shortIdentifier}$$",
"display": {
"title": "$${rawdata.title}$$"
},
"customParams": {
"blogId": "**methods.getBlogId(resource)**",
"shortIdentifier": "**methods.getShortId(resource)**"
},
"methods": {
"getShortId": "return resource.identifier.split('-post-')[1];",
"getBlogId": "const arr = resource.identifier.split('-post-'); const id = arr[0]; return id.startsWith('q-blog-') ? id.substring(7) : id;"
}
}
]
}

View File

@ -1190,6 +1190,9 @@
"friend10": "Edit friend",
"friend11": "Following",
"friend12": "Friends",
"friend13": "Feed"
"friend13": "Feed",
"friend14": "Remove friend",
"friend15": "Feed settings",
"friend16": "Select the Q-Apps you want updates from, especially those related to your friends."
}
}

View File

@ -10,8 +10,10 @@ import {
import '@material/mwc-button';
import '@material/mwc-dialog';
import '@material/mwc-checkbox';
import { connect } from 'pwa-helpers';
import { store } from '../../store';
class AddFriendsModal extends LitElement {
class AddFriendsModal extends connect(store)(LitElement) {
static get properties() {
return {
isOpen: { type: Boolean },
@ -21,9 +23,11 @@ class AddFriendsModal extends LitElement {
alias: { type: String },
willFollow: { type: Boolean },
notes: { type: String },
onSubmit: {attribute: false},
editContent: {type: Object},
onClose: {attribute: false}
onSubmit: { attribute: false },
editContent: { type: Object },
onClose: { attribute: false },
mySelectedFeeds: { type: Array },
availableFeeedSchemas: {type: Array}
};
}
@ -34,18 +38,22 @@ class AddFriendsModal extends LitElement {
this.alias = '';
this.willFollow = true;
this.notes = '';
this.nodeUrl = this.getNodeUrl();
this.myNode = this.getMyNode();
this.mySelectedFeeds = [];
this.availableFeeedSchemas = []
}
static get styles() {
return css`
* {
--mdc-theme-primary: rgb(3, 169, 244);
--mdc-theme-secondary: var(--mdc-theme-primary);
--mdc-theme-surface: var(--white);
--mdc-dialog-content-ink-color: var(--black);
--mdc-dialog-min-width: 400px;
--mdc-dialog-max-width: 1024px;
}
* {
--mdc-theme-primary: rgb(3, 169, 244);
--mdc-theme-secondary: var(--mdc-theme-primary);
--mdc-theme-surface: var(--white);
--mdc-dialog-content-ink-color: var(--black);
--mdc-dialog-min-width: 400px;
--mdc-dialog-max-width: 1024px;
}
.input {
width: 90%;
outline: 0;
@ -69,9 +77,36 @@ class AddFriendsModal extends LitElement {
color: var(--black);
}
.close-button {
display: block;
--mdc-theme-primary: red;
.modal-button {
font-family: Roboto, sans-serif;
font-size: 16px;
color: var(--mdc-theme-primary);
background-color: transparent;
padding: 8px 10px;
border-radius: 5px;
border: none;
transition: all 0.3s ease-in-out;
}
.modal-button-red {
font-family: Roboto, sans-serif;
font-size: 16px;
color: #f44336;
background-color: transparent;
padding: 8px 10px;
border-radius: 5px;
border: none;
transition: all 0.3s ease-in-out;
}
.modal-button-red:hover {
cursor: pointer;
background-color: #f4433663;
}
.modal-button:hover {
cursor: pointer;
background-color: #03a8f475;
}
.checkbox-row {
position: relative;
@ -83,167 +118,331 @@ class AddFriendsModal extends LitElement {
color: var(--black);
}
.modal-overlay {
display: block;
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background-color: rgba(0, 0, 0, 0.5); /* Semi-transparent backdrop */
z-index: 1000;
}
.modal-content {
display: block;
position: fixed;
top: 50vh;
left: 50vw;
transform: translate(-50%, -50%);
background-color: var(--mdc-theme-surface);
width: 80vw;
max-width: 600px;
padding: 20px;
box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 6px;
z-index: 1001;
border-radius: 5px;
max-height: 80vh;
overflow: auto;
}
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background-color: rgba(
0,
0,
0,
0.5
); /* Semi-transparent backdrop */
z-index: 1000;
}
.modal-content {
position: fixed;
top: 50vh;
left: 50vw;
transform: translate(-50%, -50%);
background-color: var(--mdc-theme-surface);
width: 80vw;
max-width: 600px;
padding: 20px;
box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 6px;
z-index: 1001;
border-radius: 5px;
max-height: 80vh;
overflow: auto;
}
.modal-overlay.hidden {
display: none;
}
display: none;
}
.avatar {
width: 36px;
height: 36px;
display: flex;
align-items: center;
}
.app-name {
display: flex;
gap: 20px;
align-items: center;
width: 100%;
cursor: pointer;
padding: 5px;
border-radius: 5px;
margin-bottom: 10px;
}
`;
}
firstUpdated() {}
clearFields(){
getNodeUrl() {
const myNode =
store.getState().app.nodeConfig.knownNodes[
window.parent.reduxStore.getState().app.nodeConfig.node
];
const nodeUrl =
myNode.protocol + '://' + myNode.domain + ':' + myNode.port;
return nodeUrl;
}
getMyNode() {
const myNode =
store.getState().app.nodeConfig.knownNodes[
window.parent.reduxStore.getState().app.nodeConfig.node
];
return myNode;
}
clearFields() {
this.alias = '';
this.willFollow = true;
this.notes = '';
}
addFriend(){
addFriend() {
this.onSubmit({
name: this.userSelected.name,
alias: this.alias,
notes: this.notes,
willFollow: this.willFollow,
mySelectedFeeds: this.mySelectedFeeds
});
this.clearFields();
this.onClose();
}
this.onSubmit({
name: this.userSelected.name,
alias: this.alias,
notes: this.notes,
willFollow: this.willFollow
})
this.clearFields()
this.onClose()
}
removeFriend() {
this.onSubmit(
{
name: this.userSelected.name,
alias: this.alias,
notes: this.notes,
willFollow: this.willFollow,
mySelectedFeeds: this.mySelectedFeeds
},
true
);
this.clearFields();
this.onClose();
}
async updated(changedProperties) {
if (changedProperties && changedProperties.has('editContent') && this.editContent) {
if (
changedProperties &&
changedProperties.has('editContent') &&
this.editContent
) {
this.userSelected = {
name: this.editContent.name ?? '',
}
this.notes = this.editContent.notes ?? ''
this.willFollow = this.editContent.willFollow ?? true
this.alias = this.editContent.alias ?? ''
};
this.notes = this.editContent.notes ?? '';
this.willFollow = this.editContent.willFollow ?? true;
this.alias = this.editContent.alias ?? '';
}
if (
changedProperties &&
changedProperties.has('isOpen') && this.isOpen
) {
this.getAvailableFeedSchemas()
}
}
async getAvailableFeedSchemas() {
try {
const url = `${this.nodeUrl}/arbitrary/resources/search?service=DOCUMENT&identifier=ui_schema_feed&prefix=true`;
const res = await fetch(url);
const data = await res.json();
if (data.error === 401) {
this.availableFeeedSchemas = [];
} else {
const result = data.filter(
(item) => item.identifier === 'ui_schema_feed'
);
this.availableFeeedSchemas = result;
}
this.userFoundModalOpen = true;
} catch (error) {}
}
render() {
return html`
<div class="modal-overlay ${this.isOpen ? '' : 'hidden'}">
<div class="modal-content">
<div style="text-align:center">
<h1>${this.editContent ? translate('friends.friend10') : translate('friends.friend2')}</h1>
<hr />
</div>
<p>${translate('friends.friend3')}</p>
<div class="checkbox-row">
<label
for="willFollow"
id="willFollowLabel"
style="color: var(--black);"
<div class="modal-overlay ${this.isOpen ? '' : 'hidden'}">
<div class="modal-content">
<div style="text-align:center">
<h1>
${this.editContent
? translate('friends.friend10')
: translate('friends.friend2')}
</h1>
<hr />
</div>
<p>${translate('friends.friend3')}</p>
<div class="checkbox-row">
<label
for="willFollow"
id="willFollowLabel"
style="color: var(--black);"
>
${get('friends.friend5')}
</label>
<mwc-checkbox
style="margin-right: -15px;"
id="willFollow"
@change=${(e) => {
this.willFollow = e.target.checked;
}}
?checked=${this.willFollow}
></mwc-checkbox>
</div>
<div style="height: 15px"></div>
<div style="display: flex;flex-direction: column;">
<label
for="name"
id="nameLabel"
style="color: var(--black);"
>
${get('login.name')}
</label>
<input
id="name"
class="input"
?disabled=${true}
value=${this.userSelected
? this.userSelected.name
: ''}
/>
</div>
<div style="height: 15px"></div>
<div style="display: flex;flex-direction: column;">
<label
for="alias"
id="aliasLabel"
style="color: var(--black);"
>
${get('friends.friend6')}
</label>
<input
id="alias"
placeholder=${translate('friends.friend7')}
class="input"
value=${this.alias}
@change=${(e) => (this.alias = e.target.value)}
/>
</div>
<div style="height: 15px"></div>
<div style="margin-bottom:0;">
<textarea
class="input"
@change=${(e) => (this.notes = e.target.value)}
value=${this.notes}
?disabled=${this.isLoading}
id="messageBoxAddFriend"
placeholder="${translate('friends.friend4')}"
rows="3"
></textarea>
</div>
<div style="height: 15px"></div>
<h2>${translate('friends.friend15')}</h2>
<div style="margin-bottom:0;">
<p>${translate('friends.friend16')}</p>
</div>
<div>
${this.availableFeeedSchemas.map((schema) => {
const isAlreadySelected = this.mySelectedFeeds.find(
(item) => item.name === schema.name
);
let avatarImgApp;
const avatarUrl2 = `${this.nodeUrl}/arbitrary/THUMBNAIL/${schema.name}/qortal_avatar?async=true&apiKey=${this.myNode.apiKey}`;
avatarImgApp = html`<img
src="${avatarUrl2}"
style="max-width:100%; max-height:100%;"
onerror="this.onerror=null; this.src='/img/incognito.png';"
/>`;
return html`
<div
class="app-name"
style="background:${isAlreadySelected ? 'lightblue': ''}"
@click=${() => {
const copymySelectedFeeds = [
...this.mySelectedFeeds,
];
const findIndex =
copymySelectedFeeds.findIndex(
(item) =>
item.name === schema.name
);
if (findIndex === -1) {
copymySelectedFeeds.push({
name: schema.name,
identifier: schema.identifier,
service: schema.service,
});
this.mySelectedFeeds =
copymySelectedFeeds;
} else {
this.mySelectedFeeds =
copymySelectedFeeds.filter(
(item) =>
item.name !==
schema.name
);
}
}}
>
<div class="avatar">${avatarImgApp}</div>
<span
style="color:${isAlreadySelected ? 'var(--white)': 'var(--black)'};font-size:16px"
>${schema.name}</span
>
</div>
`;
})}
</div>
<div
style="display:flex;justify-content:space-between;align-items:center;margin-top:20px"
>
${get('friends.friend5')}
</label>
<mwc-checkbox
style="margin-right: -15px;"
id="willFollow"
@change=${(e) => {
this.willFollow = e.target.checked;
}}
?checked=${this.willFollow}
></mwc-checkbox>
</div>
<div style="height: 15px"></div>
<div style="display: flex;flex-direction: column;">
<label
for="name"
id="nameLabel"
style="color: var(--black);"
>
${get('login.name')}
</label>
<input
id="name"
class="input"
?disabled=${true}
value=${this.userSelected ? this.userSelected.name : ''}
/>
</div>
<div style="height: 15px"></div>
<div style="display: flex;flex-direction: column;">
<label
for="alias"
id="aliasLabel"
style="color: var(--black);"
>
${get('friends.friend6')}
</label>
<input
id="alias"
placeholder=${translate('friends.friend7')}
class="input"
value=${this.alias}
@change=${(e) => (this.alias = e.target.value)}
/>
</div>
<div style="height: 15px"></div>
<div style="margin-bottom:0;">
<textarea
class="input"
@change=${(e) => (this.notes = e.target.value)}
value=${this.notes}
?disabled=${this.isLoading}
id="messageBoxAddFriend"
placeholder="${translate('friends.friend4')}"
rows="3"
></textarea>
</div>
<div style="display:flex;justify-content:space-between;align-items:center;margin-top:20px">
<mwc-button
?disabled="${this.isLoading}"
slot="secondaryAction"
@click="${() => {
this.setIsOpen(false)
this.clearFields()
this.onClose()
} }"
class="close-button"
>
${translate('general.close')}
</mwc-button>
<mwc-button
?disabled="${this.isLoading}"
slot="primaryAction"
@click=${() => {
this.addFriend();
}}
>${this.editContent ? translate('friends.friend10') : translate('friends.friend2')}
</mwc-button>
</div>
</div>
<button
class="modal-button-red"
?disabled="${this.isLoading}"
@click="${() => {
this.setIsOpen(false);
this.clearFields();
this.onClose();
}}"
>
${translate('general.close')}
</button>
${this.editContent
? html`
<button
?disabled="${this.isLoading}"
class="modal-button-red"
@click=${() => {
this.removeFriend();
}}
>
${translate('friends.friend14')}
</button>
`
: ''}
<button
?disabled="${this.isLoading}"
class="modal-button"
@click=${() => {
this.addFriend();
}}
>
${this.editContent
? translate('friends.friend10')
: translate('friends.friend2')}
</button>
</div>
</div>
</div>
`;
}
}

View File

@ -13,7 +13,10 @@ import { store } from '../../store';
import { setNewTab } from '../../redux/app/app-actions';
import ShortUniqueId from 'short-unique-id';
const requestQueue = new RequestQueueWithPromise(5);
const requestQueue = new RequestQueueWithPromise(3);
const requestQueueRawData = new RequestQueueWithPromise(3);
const requestQueueStatus = new RequestQueueWithPromise(3);
export class FeedItem extends connect(store)(LitElement) {
static get properties() {
@ -140,7 +143,6 @@ export class FeedItem extends connect(store)(LitElement) {
this.status = {
status: ''
}
this.url = ""
this.isReady = false
this.nodeUrl = this.getNodeUrl()
this.myNode = this.getMyNode()
@ -195,21 +197,23 @@ getMyNode(){
async fetchVideoUrl() {
this.fetchResource()
this.url = `${this.nodeUrl}/arbitrary/${this.resource.service}/${this.resource.name}/${this.resource.identifier}?async=true&apiKey=${this.myNode.apiKey}`
}
async getRawData(){
const url = `${this.nodeUrl}/arbitrary/${this.resource.service}/${this.resource.name}/${this.resource.identifier}?apiKey=${this.myNode.apiKey}`
const response2 = await fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
return await requestQueueRawData.enqueue(()=> {
return axios.get(url)
})
// const response2 = await fetch(url, {
// method: 'GET',
// headers: {
// 'Content-Type': 'application/json'
// }
// })
const responseData2 = await response2.json()
return responseData2
// const responseData2 = await response2.json()
// return responseData2
}
updateDisplayWithPlaceholders(display, resource, rawdata) {
@ -244,13 +248,16 @@ getMyNode(){
let isCalling = false
let percentLoaded = 0
let timer = 24
const response = await axios.get(`${this.nodeUrl}/arbitrary/resource/status/${this.resource.service}/${this.resource.name}/${this.resource.identifier}?apiKey=${this.myNode.apiKey}`)
const response = await requestQueueStatus.enqueue(()=> {
return axios.get(`${this.nodeUrl}/arbitrary/resource/status/${this.resource.service}/${this.resource.name}/${this.resource.identifier}?apiKey=${this.myNode.apiKey}`)
})
if(response && response.data && response.data.status === 'READY'){
const rawData = await this.getRawData()
console.log({rawData})
const object = {
title: "$${rawdata.title}$$",
...this.resource.schema.display
}
this.updateDisplayWithPlaceholders(object, {},rawData)
this.updateDisplayWithPlaceholders(object, {},rawData.data)
this.feedItem = object
this.status = response.data
@ -301,8 +308,12 @@ getMyNode(){
// check if progress is 100% and clear interval if true
if (res.status === 'READY') {
this.feedItem = await this.getRawData()
const rawData = await this.getRawData()
const object = {
...this.resource.schema.display
}
this.updateDisplayWithPlaceholders(object, {},rawData.data)
this.feedItem = object
clearInterval(intervalId)
this.status = res
this.isReady = true
@ -312,11 +323,7 @@ getMyNode(){
async _fetchImage() {
try {
this.fetchVideoUrl({
name: this.resource.name,
service: this.resource.service,
identifier: this.resource.identifier
})
this.fetchVideoUrl()
this.fetchStatus()
} catch (error) { /* empty */ }
}

View File

@ -90,7 +90,6 @@ export class FriendItemActions extends connect(store)(LitElement) {
}
attachToTarget(target) {
console.log({ target });
if (!this.popperInstance && target) {
this.popperInstance = createPopper(target, this, {
placement: 'bottom',

View File

@ -5,6 +5,8 @@ import { friendsViewStyles } from './friends-view-css';
import { connect } from 'pwa-helpers';
import { store } from '../../store';
import './feed-item'
import '@polymer/paper-spinner/paper-spinner-lite.js'
const perEndpointCount = 20;
const totalDesiredCount = 100;
@ -13,7 +15,8 @@ class FriendsFeed extends connect(store)(LitElement) {
static get properties() {
return {
feed: {type: Array},
setHasNewFeed: {attribute:false}
setHasNewFeed: {attribute:false},
isLoading: {type: Boolean}
};
}
constructor(){
@ -57,30 +60,84 @@ class FriendsFeed extends connect(store)(LitElement) {
return myNode;
}
async getSchemas(schemas){
const getAllSchemas = (schemas || []).map(
async (schema) => {
try {
const url = `${this.nodeUrl}/arbitrary/${schema.service}/${schema.name}/${schema.identifier}`;
const res = await fetch(url)
const data = await res.json()
if(data.error) return false
return data
} catch (error) {
console.log(error);
return false
}
}
);
const res = await Promise.all(getAllSchemas);
return res.filter((item)=> !!item)
}
getFeedOnInterval(){
let interval = null;
let stop = false;
const getAnswer = async () => {
if (!stop) {
stop = true;
try {
await this.reFetchFeedData()
} catch (error) {}
stop = false;
}
};
interval = setInterval(getAnswer, 600000);
}
async firstUpdated(){
this.viewElement = this.shadowRoot.getElementById('viewElement');
this.downObserverElement =
this.shadowRoot.getElementById('downObserver');
this.elementObserver();
const feedData = schema.feed[0]
let schemaObj = {...schema}
const dynamicVars = {
}
const getEndpoints = async () => {
const baseurl = `${this.nodeUrl}/arbitrary/resources/search?reverse=true`
const fullUrl = constructUrl(baseurl, feedData.search, dynamicVars);
this.endpoints= [{url: fullUrl, schemaName: schema.name, schema: feedData }]
this.endpointOffsets = Array(this.endpoints.length).fill(0);
const schemas = await this.getSchemas(schemaList)
const friendList = JSON.parse(localStorage.getItem('friends-my-friend-list') || "[]")
console.log({friendList})
const names = friendList.map(friend => `name=${friend.name}`).join('&');
console.log({names})
const baseurl = `${this.nodeUrl}/arbitrary/resources/search?reverse=true&exactmatchnames=true&${names}`
let formEndpoints = []
schemas.forEach((schema)=> {
const feedData = schema.feed[0]
if(feedData){
const copyFeedData = {...feedData}
const fullUrl = constructUrl(baseurl, copyFeedData.search, dynamicVars);
if(fullUrl){
formEndpoints.push({
url: fullUrl, schemaName: schema.name, schema: copyFeedData
})
}
}
})
this.endpoints= formEndpoints
this.endpointOffsets = Array(this.endpoints.length).fill(0);
}
try {
getEndpoints()
await getEndpoints()
this.loadAndMergeData();
this.getFeedOnInterval()
} catch (error) {
console.log(error)
@ -147,7 +204,7 @@ this.loadAndMergeData();
while (totalFetched < totalDesiredCount && madeProgress) {
madeProgress = false;
this.isLoading = true
for (i = 0; i < this.endpoints.length; i++) {
if (exhaustedEndpoints.has(i)) {
continue;
@ -182,7 +239,7 @@ this.loadAndMergeData();
break;
}
}
this.isLoading = false
// Trim the results if somehow they are over the totalDesiredCount
return results.slice(0, totalDesiredCount);
}
@ -233,6 +290,37 @@ this.loadAndMergeData();
return newData
}
async reFetchFeedData() {
// Resetting offsets to start fresh.
this.endpointOffsets = Array(this.endpoints.length).fill(0);
const oldIdentifiers = new Set(this.feed.map(item => item.identifier));
const newData = await this.initialLoad();
// Filter out items that are already in the feed
const trulyNewData = newData.filter(item => !oldIdentifiers.has(item.identifier));
if (trulyNewData.length > 0) {
// Adding extra data and merging with old data
const enhancedNewData = await this.addExtraData(trulyNewData);
// Merge new data with old data immutably
this.feed = [...enhancedNewData, ...this.feed];
this.feed.sort((a, b) => new Date(b.created) - new Date(a.created)); // Sort by timestamp, most recent first
this.feed = this.trimDataToLimit(this.feed, maxResultsInMemory); // Trim to the maximum allowed in memory
this.feedToRender = this.feed.slice(0, 20);
this.hasInitialFetch = true;
const created = trulyNewData[0].created;
let value = localStorage.getItem('lastSeenFeed');
if (((+value || 0) < created)) {
this.setHasNewFeed(true);
}
}
}
async loadAndMergeData() {
let allData = this.feed
@ -261,7 +349,11 @@ this.loadAndMergeData();
return html`
<div class="container">
<div id="viewElement" class="container-body" style=${"position: relative"}>
${this.isLoading ? html`
<div style="width:100%;display: flex; justify-content:center">
<paper-spinner-lite active></paper-spinner-lite>
</div>
` : ''}
${this.feedToRender.map((item) => {
return html`<feed-item
.resource=${item}
@ -351,6 +443,7 @@ function executeMethodInWorker(methodString, externalArgs) {
URL.revokeObjectURL(blobURL);
} else {
resolve("");
event.data = null
worker.terminate();
URL.revokeObjectURL(blobURL);
}
@ -409,9 +502,12 @@ export function replacePlaceholders(template, resource, customParams) {
// export const schemaList = [schema]
const schema = {
export const schemaList = [{
identifier: 'ui_schema_feed',
name: 'Q-Blog',
service: 'DOCUMENT'
}]
export const schema = {
name: "Q-Blog",
defaultFeedIndex: 0,
feed: [
@ -429,9 +525,7 @@ export function replacePlaceholders(template, resource, customParams) {
},
click: "qortal://APP/Q-Blog/$${resource.name}$$/$${customParams.blogId}$$/$${customParams.shortIdentifier}$$",
display: {
title: "$${rawdata.title}$$",
description: "$${rawdata.description}$$",
coverImage: "$${rawdata.image}$$"
title: "$${rawdata.title}$$"
},
customParams: {
blogId: "**methods.getBlogId(resource)**",
@ -446,3 +540,4 @@ export function replacePlaceholders(template, resource, customParams) {
]
}
export const listSchemas = [schema]

View File

@ -107,9 +107,15 @@ class FriendsSidePanel extends LitElement {
<span @click=${()=> this.selected = 'friends'} class="${this.selected === 'friends' ? 'active' : 'default'}">${translate('friends.friend12')}</span>
<span @click=${()=> this.selected = 'feed'} class="${this.selected === 'feed' ? 'active' : 'default'}">${translate('friends.friend13')}</span>
</div>
<div style="display:flex;gap:15px;align-items:center">
<mwc-icon @click=${()=> {
this.shadowRoot.querySelector('friends-feed').reFetchFeedData()
}} style="color: var(--black); cursor:pointer;">refresh</mwc-icon>
<mwc-icon style="cursor:pointer" @click=${()=> {
this.setIsOpen(false)
}}>close</mwc-icon>
</div>
</div>
<div class="content">
<div class="${this.selected === 'friends' ? 'active-content' : 'default-content'}">
@ -118,9 +124,7 @@ class FriendsSidePanel extends LitElement {
<div class="${this.selected === 'feed' ? 'active-content' : 'default-content'}">
<friends-feed .setHasNewFeed=${(val)=> this.setHasNewFeed(val)}></friends-feed>
</div>
<!-- ${this.selected === 'friends' ? html`<friends-view></friends-view>` : ''}
${this.selected === 'feed' ? html`<friends-feed></friends-feed>` : ''} -->
</div>

View File

@ -40,7 +40,8 @@ class FriendsView extends connect(store)(LitElement) {
userFoundModalOpen: {type: Boolean},
userFound: { type: Array},
isOpenAddFriendsModal: {type: Boolean},
editContent: {type: Object}
editContent: {type: Object},
mySelectedFeeds: {type: Array}
};
}
static get styles() {
@ -57,11 +58,7 @@ class FriendsView extends connect(store)(LitElement) {
window.parent.reduxStore.getState().app.selectedAddress.address;
this.errorMessage = '';
this.successMessage = '';
this.friendList = [{
name: "Phil"
}];
this.friendList = [];
this.userSelected = {};
this.isLoading = false;
this.userFoundModalOpen = false
@ -99,6 +96,8 @@ class FriendsView extends connect(store)(LitElement) {
this.downObserverElement =
this.shadowRoot.getElementById('downObserver');
this.elementObserver();
this.mySelectedFeeds = JSON.parse(localStorage.getItem('friends-my-selected-feeds') || "[]")
this.friendList = JSON.parse(localStorage.getItem('friends-my-friend-list') || "[]")
}
elementObserver() {
@ -177,41 +176,68 @@ class FriendsView extends connect(store)(LitElement) {
body: `${namesJsonString}`
})
if (ret === true) {
this.myFollowedNames = this.myFollowedNames.filter(item => item != name)
this.myFollowedNames.push(name)
} else {
let err3string = get("appspage.schange22")
parentEpml.request('showSnackBar', `${err3string}`)
}
return ret
}
addToFriendList(val){
if(this.editContent){
const findFriend = this.friendList.findIndex(item=> item.name === val.name)
async unFollowName(name) {
let items = [
name
]
let namesJsonString = JSON.stringify({ "items": items })
let ret = await parentEpml.request('apiCall', {
url: `/lists/followedNames?apiKey=${this.getApiKey()}`,
method: 'DELETE',
headers: {
'Content-Type': 'application/json'
},
body: `${namesJsonString}`
})
return ret
}
addToFriendList(val, isRemove){
const copyVal = {...val}
delete copyVal.mySelectedFeeds
if(isRemove){
this.friendList = this.friendList.filter((item)=> item.name !== copyVal.name)
}else if(this.editContent){
const findFriend = this.friendList.findIndex(item=> item.name === copyVal.name)
if(findFriend !== -1){
const copyList = [...this.friendList]
copyList[findFriend] = val
copyList[findFriend] = copyVal
this.friendList = copyList
}
} else {
this.friendList = [...this.friendList, val]
this.friendList = [...this.friendList, copyVal]
}
if(val.willFollow){
this.myFollowName(val.name)
}
if(!copyVal.willFollow || isRemove) {
this.unFollowName(copyVal.name)
} else if(copyVal.willFollow){
this.myFollowName(copyVal.name)
}
this.setMySelectedFeeds(val.mySelectedFeeds)
this.userSelected = {};
this.isLoading = false;
this.isOpenAddFriendsModal = false
this.editContent = null
this.setMyFriends(this.friendList)
}
setMyFriends(friendList){
localStorage.setItem('friends-my-friend-list', JSON.stringify(friendList));
}
setMySelectedFeeds(mySelectedFeeds){
this.mySelectedFeeds = mySelectedFeeds
localStorage.setItem('friends-my-selected-feeds', JSON.stringify(mySelectedFeeds));
}
openEditFriend(val){
this.isOpenAddFriendsModal = true
this.userSelected = val
this.editContent = val
this.editContent = {...val, mySelectedFeeds: this.mySelectedFeeds}
}
onClose(){
@ -288,9 +314,10 @@ class FriendsView extends connect(store)(LitElement) {
this.isOpenAddFriendsModal = val
}}
.userSelected=${this.userSelected}
.onSubmit=${(val)=> this.addToFriendList(val)}
.onSubmit=${(val, isRemove)=> this.addToFriendList(val, isRemove)}
.editContent=${this.editContent}
.onClose=${()=> this.onClose()}
.mySelectedFeeds=${this.mySelectedFeeds}
>
</add-friends-modal>
`;

View File

@ -40,7 +40,6 @@ export class PopoverComponent extends LitElement {
}
attachToTarget(target) {
console.log({target})
if (!this.popperInstance && target) {
this.popperInstance = createPopper(target, this, {
placement: 'bottom',