Added "Matches" page

Matches page will show the follows/followers and both following as:
 People matched me / I matched people / We matched together
For this feature to work we have to make sure the Mastodon account is private,
 because we will use the "accept friend request" as a "both match"

Fixes:
* Improved chat painting intervals
* Added matches intl and new pages
* Fixed Toast UI
* Fixed a bug where home will not display correctly when before login
* Removed notification options from settings
* Improved code stability
* Added "myAccountId" fediloveData, which contains the user account id
* Replaced localStorage.userAccountId for fediloveData.myAccountId
* Improved path URL handling for /settings and /accounts
This commit is contained in:
Bofh 2021-01-07 01:25:04 +01:00
parent 4681c5a3e3
commit c1cb2f212e
8 changed files with 110 additions and 70 deletions

View File

@ -61,6 +61,7 @@ export default {
home: 'Home', home: 'Home',
meet: 'Meet!', meet: 'Meet!',
notifications: 'Notifications', notifications: 'Notifications',
matches: 'Matches',
mutedUsers: 'Muted users', mutedUsers: 'Muted users',
pinnedStatuses: 'Pinned toots', pinnedStatuses: 'Pinned toots',
followRequests: 'Follow requests', followRequests: 'Follow requests',

View File

@ -25,7 +25,6 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
border: 2px solid var(--toast-border);
background: var(--toast-bg); background: var(--toast-bg);
border-radius: 5px; border-radius: 5px;
margin: 0 40px; margin: 0 40px;

View File

@ -0,0 +1,20 @@
<DynamicPageBanner title="{intl.follows}" />
<AccountsListPage {accountsFetcher} />
<script>
import { getFollows } from '../../_api/followsAndFollowers'
import AccountsListPage from '../../_components/AccountsListPage.html'
import { store } from '../../_store/store'
import DynamicPageBanner from '../../_components/DynamicPageBanner.html'
export default {
computed: {
accountId: ({ params }) => params.accountId,
accountsFetcher: ({ $currentInstance, $accessToken, accountId }) => () => getFollows($currentInstance, $accessToken, accountId)
},
store: () => store,
components: {
AccountsListPage,
DynamicPageBanner
}
}
</script>

View File

@ -4,12 +4,6 @@
{#if verifyCredentials} {#if verifyCredentials}
<h2>{intl.loggedInAs}</h2> <h2>{intl.loggedInAs}</h2>
<InstanceUserProfile {verifyCredentials} /> <InstanceUserProfile {verifyCredentials} />
<h2>{intl.homeTimelineFilters}</h2>
<HomeTimelineFilterSettings {instanceName} />
<h2>{intl.notificationFilters}</h2>
<NotificationFilterSettings {instanceName} />
<h2>{intl.pushNotifications}</h2>
<PushNotificationSettings {instanceName} />
<InstanceActions {instanceName} /> <InstanceActions {instanceName} />
{/if} {/if}
@ -25,9 +19,6 @@
import { store } from '../../../_store/store' import { store } from '../../../_store/store'
import SettingsLayout from '../../../_components/settings/SettingsLayout.html' import SettingsLayout from '../../../_components/settings/SettingsLayout.html'
import InstanceUserProfile from '../../../_components/settings/instance/InstanceUserProfile.html' import InstanceUserProfile from '../../../_components/settings/instance/InstanceUserProfile.html'
import HomeTimelineFilterSettings from '../../../_components/settings/instance/HomeTimelineFilterSettings.html'
import NotificationFilterSettings from '../../../_components/settings/instance/NotificationFilterSettings.html'
import PushNotificationSettings from '../../../_components/settings/instance/PushNotificationSettings.html'
import InstanceActions from '../../../_components/settings/instance/InstanceActions.html' import InstanceActions from '../../../_components/settings/instance/InstanceActions.html'
import { updateVerifyCredentialsForInstance } from '../../../_actions/instances' import { updateVerifyCredentialsForInstance } from '../../../_actions/instances'
@ -44,10 +35,7 @@
components: { components: {
SettingsLayout, SettingsLayout,
InstanceUserProfile, InstanceUserProfile,
PushNotificationSettings, InstanceActions
InstanceActions,
HomeTimelineFilterSettings,
NotificationFilterSettings
} }
} }
</script> </script>

View File

@ -74,9 +74,9 @@ export function navComputations (store) {
}, },
{ {
name: 'notifications', name: 'notifications',
href: '/notifications', href: '/matches',
svg: '#fa-asterisk', svg: '#fa-asterisk',
label: 'intl.notifications' label: 'intl.matches'
}, },
{ {
name: 'direct', name: 'direct',

View File

@ -0,0 +1,19 @@
<Title name="{intl.follows}" />
<LazyPage {pageComponent} {params} />
<script>
import Title from '../_components/Title.html'
import LazyPage from '../_components/LazyPage.html'
import pageComponent from '../_pages/matches/index.html'
export default {
components: {
Title,
LazyPage
},
data: () => ({
pageComponent
})
}
</script>

View File

@ -59,6 +59,7 @@ $deemphasized-text-color: #939393;
--article-bg: #{$article-bg}; --article-bg: #{$article-bg};
--focus-outline: #{$button-primary-hover}; --focus-outline: #{$button-primary-hover};
--focus-width: 1px; --focus-width: 1px;
--toast-text: #{$main-text-color};
--deemphasized-text-color: #{$deemphasized-text-color}; --deemphasized-text-color: #{$deemphasized-text-color};
--very-deemphasized-text-color: #{$deemphasized-text-color}; --very-deemphasized-text-color: #{$deemphasized-text-color};
} }

View File

@ -9,12 +9,17 @@ function mastodon_get(path, payload, callbk) { return mastodon_request('GET',
function mastodon_post(path, payload, callbk) { return mastodon_request('POST', path, payload, callbk); } function mastodon_post(path, payload, callbk) { return mastodon_request('POST', path, payload, callbk); }
function mastodon_request(method, path, payload, callbk) { function mastodon_request(method, path, payload, callbk) {
payload = payload || null; payload = payload || null;
var url = 'https://'+fediloveApi.getCurrentInstance()+path;
var oReq = new XMLHttpRequest(); const ACCESS_TOKEN = window.fediloveApi.getAccessToken();
if (ACCESS_TOKEN === undefined)
return callbk(undefined);
const API_URL = 'https://'+fediloveApi.getCurrentInstance()+path;
const oReq = new XMLHttpRequest();
oReq.addEventListener("load", function() { callbk(this.responseText); }); oReq.addEventListener("load", function() { callbk(this.responseText); });
oReq.open(method, url); oReq.open(method, API_URL);
oReq.setRequestHeader('Authorization', 'Bearer '+fediloveApi.getAccessToken()); oReq.setRequestHeader('Authorization', 'Bearer '+ACCESS_TOKEN);
oReq.send(payload); oReq.send(payload);
} }
@ -240,10 +245,14 @@ var fediloveApi = {
return andUuid? { id: parts[parts.length-1], uuid: lastUuid } : parts[parts.length-1]; return andUuid? { id: parts[parts.length-1], uuid: lastUuid } : parts[parts.length-1];
}, },
getAccessToken: function() { getAccessToken: function() {
var instance = fediloveApi.getCurrentInstance(); const instance = fediloveApi.getCurrentInstance();
if (instance === undefined)
return undefined;
return JSON.parse(localStorage.store_loggedInInstances)[instance].access_token; return JSON.parse(localStorage.store_loggedInInstances)[instance].access_token;
}, },
getCurrentInstance: function() { getCurrentInstance: function() {
if (localStorage.store_currentInstance === undefined)
return undefined;
return JSON.parse(localStorage.store_currentInstance); return JSON.parse(localStorage.store_currentInstance);
} }
}; };
@ -265,6 +274,7 @@ var fediloveData = {
chatAvatarCache: undefined, chatAvatarCache: undefined,
meetAccountCurrentImg: 0, meetAccountCurrentImg: 0,
meetAccountImageLocked: false, meetAccountImageLocked: false,
myAccountId: undefined,
currentAccount: null, currentAccount: null,
currentAccountIsEmpty: false, currentAccountIsEmpty: false,
gotEmojifyTextFunction: false, gotEmojifyTextFunction: false,
@ -298,7 +308,7 @@ var fediloveEvents = {
if (data) { if (data) {
// if the message is mine, search which account is doing it for, // if the message is mine, search which account is doing it for,
// and do the same with the party's data // and do the same with the party's data
if (localStorage.store_userAccountId == data.account.id) { if (fediloveData.myAccountId == data.account.id) {
var account_id = data.in_reply_to_account_id; var account_id = data.in_reply_to_account_id;
if (account_id === null && data.mentions.length > 0) { if (account_id === null && data.mentions.length > 0) {
account_id = data.mentions[0].id; account_id = data.mentions[0].id;
@ -340,7 +350,7 @@ function fedilove_customization() {
document.body.classList = ''; document.body.classList = '';
document.getElementById('sapper').style = ''; document.getElementById('sapper').style = '';
if (localStorage.store_currentInstance === "undefined") { if ([undefined,"undefined"].includes(localStorage.store_currentInstance)) {
$('body').addClass('not-logged-in'); $('body').addClass('not-logged-in');
if (window.location.pathname == '/') { if (window.location.pathname == '/') {
$('body').addClass('home'); $('body').addClass('home');
@ -348,6 +358,17 @@ function fedilove_customization() {
return; return;
} }
// get the userAccountId to check against the href /account/NUM on the messages
// so we can apply different style to my messages
if (fediloveData.myAccountId === undefined) {
mastodon_get('/api/v1/accounts/verify_credentials', {}, function(data) {
const json = JSON.parse(data);
if (json !== undefined) {
fediloveData.myAccountId = json.id;
}
});
}
if (document.querySelector('#main-nav > div#dummy-nav') != null) { if (document.querySelector('#main-nav > div#dummy-nav') != null) {
document.querySelector('#main-nav > div#dummy-nav').remove(); document.querySelector('#main-nav > div#dummy-nav').remove();
document.querySelector('#main-nav > ul.main-nav-ul').style = ''; document.querySelector('#main-nav > ul.main-nav-ul').style = '';
@ -432,72 +453,63 @@ function fedilove_customization() {
// this function changes the css class on articles (messages) // this function changes the css class on articles (messages)
// that match the given account_id // that match the given account_id
var makeMessageUIModifications = function(account_id) { var theint = 100;
var theint = 150; const _this = setInterval(function()
const _this = setInterval(function() {
{ // interval auto-destroyer
if (!window.location.pathname.startsWith('/statuses/')) { if (!window.location.pathname.startsWith('/statuses/')) {
clearInterval(_this); clearInterval(_this);
return; return;
} }
// paint MY messages as mine // paint MY messages as mine
if (fediloveData.myAccountId !== undefined) {
$('div.main-content.chat article.status-article').each(function(i) { $('div.main-content.chat article.status-article').each(function(i) {
if ($(this).find('a.status-author-name').attr('href').endsWith(`/accounts/${account_id}`)) { if ($(this).find('a.status-author-name').attr('href').endsWith(`/accounts/${fediloveData.myAccountId}`)) {
$(this).addClass('mymsg'); $(this).addClass('mymsg');
theint = 250; theint = 250;
} else { } else {
$(this).addClass('partymsg'); $(this).addClass('partymsg');
} }
}); });
}
// paint LIKES // paint LIKES
$('a.status-favs-reblogs.status-favs').each(function(i) { $('a.status-favs-reblogs.status-favs').each(function(i) {
// easy, aria-label contains the times this status was fav // easy, aria-label contains the times this status was fav
// so, we use this as the input source to search for "0", // so, we use this as the input source to search for "0",
// if no "0" found in text, we mark element as liked so we can apply styles and "undo like" function // if no "0" found in text, we mark element as liked so we can apply styles and "undo like" function
if ($(this).attr('aria-label').search(/0/) == -1) { if ($(this).attr('aria-label').search(/0/) == -1) {
$(this).addClass('liked-msg'); $(this).addClass('liked-msg');
$(this).attr('data-liked', 1); $(this).attr('data-liked', 1);
}
});
// remove liking functionality from our own messages
$('div.the-list article.status-article.mymsg a.status-favs-reblogs').each(function(i) {
$(this).attr('onclick', 'return false;');
});
// resize likes acording to the outer parent
$('div.main-content.chat div.the-list article.status-article').each(function(e) {
$(this).find('div.like-div').width($(this).width());
});
}, theint);
};
// get the userAccountId to check against the href /account/NUM on the messages
// so we can apply different style to my messages
if (localStorage.store_userAccountId === undefined) {
mastodon_get('/api/v1/accounts/verify_credentials', {}, function(data) {
var json = JSON.parse(data);
if (json !== undefined) {
localStorage.store_userAccountId = json.id;
makeMessageUIModifications(json.id);
} }
}); });
} else {
makeMessageUIModifications(localStorage.store_userAccountId); // remove liking functionality from our own messages
} $('div.the-list article.status-article.mymsg a.status-favs-reblogs').each(function(i) {
$(this).attr('onclick', 'return false;');
});
// resize likes acording to the outer parent
$('div.main-content.chat div.the-list article.status-article').each(function(e) {
$(this).find('div.like-div').width($(this).width());
});
}, theint);
}
else if (window.location.pathname == '/matches') {
console.log('matches');
} }
else if (window.location.pathname == '/direct') { else if (window.location.pathname == '/direct') {
$('div.main-content').addClass('direct'); $('div.main-content').addClass('direct');
$('body').addClass('direct'); $('body').addClass('direct');
$('nav#main-nav li.main-nav-li svg')[2].classList += ' active'; $('nav#main-nav li.main-nav-li svg')[2].classList += ' active';
} }
else if (window.location.pathname == '/settings') { else if (window.location.pathname.startsWith('/settings')) {
$('nav#main-nav li.main-nav-li svg')[3].classList += ' active'; $('nav#main-nav li.main-nav-li svg')[3].classList += ' active';
} }
else if (window.location.pathname.startsWith('/accounts/')) else if (window.location.pathname.startsWith('/accounts/') &&
window.location.pathname.match(/^\/accounts\/\d+$/) !== null)
{ {
$('div.main-content').addClass('account'); $('div.main-content').addClass('account');
$('body').addClass('account'); $('body').addClass('account');