mirror of
https://github.com/cheeaun/phanpy.git
synced 2025-03-30 13:19:16 +03:00
Allow instance-based hashtags
Also change design a little
This commit is contained in:
parent
eebb55ba38
commit
959ac468d8
5 changed files with 117 additions and 40 deletions
|
@ -26,6 +26,8 @@
|
||||||
#shortcuts-settings-container .shortcuts-list li .shortcut-text {
|
#shortcuts-settings-container .shortcuts-list li .shortcut-text {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
line-height: 1;
|
||||||
|
word-break: break-word;
|
||||||
}
|
}
|
||||||
#shortcuts-settings-container .shortcuts-list li .shortcut-actions {
|
#shortcuts-settings-container .shortcuts-list li .shortcut-actions {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
|
|
@ -94,6 +94,13 @@ const TYPE_PARAMS = {
|
||||||
placeholder: 'e.g. PixelArt (Max 5, space-separated)',
|
placeholder: 'e.g. PixelArt (Max 5, space-separated)',
|
||||||
pattern: '[^#]+',
|
pattern: '[^#]+',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
text: 'Instance',
|
||||||
|
name: 'instance',
|
||||||
|
type: 'text',
|
||||||
|
placeholder: 'Optional, e.g. mastodon.social',
|
||||||
|
notRequired: true,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
export const SHORTCUTS_META = {
|
export const SHORTCUTS_META = {
|
||||||
|
@ -131,14 +138,15 @@ export const SHORTCUTS_META = {
|
||||||
},
|
},
|
||||||
public: {
|
public: {
|
||||||
id: 'public',
|
id: 'public',
|
||||||
title: ({ local, instance }) =>
|
title: ({ local }) => (local ? 'Local' : 'Federated'),
|
||||||
`${local ? 'Local' : 'Federated'} (${instance})`,
|
subtitle: ({ instance }) => instance,
|
||||||
path: ({ local, instance }) => `/${instance}/p${local ? '/l' : ''}`,
|
path: ({ local, instance }) => `/${instance}/p${local ? '/l' : ''}`,
|
||||||
icon: ({ local }) => (local ? 'group' : 'earth'),
|
icon: ({ local }) => (local ? 'group' : 'earth'),
|
||||||
},
|
},
|
||||||
trending: {
|
trending: {
|
||||||
id: 'trending',
|
id: 'trending',
|
||||||
title: 'Trending',
|
title: 'Trending',
|
||||||
|
subtitle: ({ instance }) => instance,
|
||||||
path: ({ instance }) => `/${instance}/trending`,
|
path: ({ instance }) => `/${instance}/trending`,
|
||||||
icon: 'chart',
|
icon: 'chart',
|
||||||
},
|
},
|
||||||
|
@ -177,6 +185,7 @@ export const SHORTCUTS_META = {
|
||||||
hashtag: {
|
hashtag: {
|
||||||
id: 'hashtag',
|
id: 'hashtag',
|
||||||
title: ({ hashtag }) => hashtag,
|
title: ({ hashtag }) => hashtag,
|
||||||
|
subtitle: ({ instance }) => instance,
|
||||||
path: ({ hashtag }) => `/t/${hashtag.split(/\s+/).join('+')}`,
|
path: ({ hashtag }) => `/t/${hashtag.split(/\s+/).join('+')}`,
|
||||||
icon: 'hashtag',
|
icon: 'hashtag',
|
||||||
},
|
},
|
||||||
|
@ -307,10 +316,13 @@ function ShortcutsSettings() {
|
||||||
const key = i + Object.values(shortcut);
|
const key = i + Object.values(shortcut);
|
||||||
const { type } = shortcut;
|
const { type } = shortcut;
|
||||||
if (!SHORTCUTS_META[type]) return null;
|
if (!SHORTCUTS_META[type]) return null;
|
||||||
let { icon, title } = SHORTCUTS_META[type];
|
let { icon, title, subtitle } = SHORTCUTS_META[type];
|
||||||
if (typeof title === 'function') {
|
if (typeof title === 'function') {
|
||||||
title = title(shortcut, i);
|
title = title(shortcut, i);
|
||||||
}
|
}
|
||||||
|
if (typeof subtitle === 'function') {
|
||||||
|
subtitle = subtitle(shortcut, i);
|
||||||
|
}
|
||||||
if (typeof icon === 'function') {
|
if (typeof icon === 'function') {
|
||||||
icon = icon(shortcut, i);
|
icon = icon(shortcut, i);
|
||||||
}
|
}
|
||||||
|
@ -319,6 +331,12 @@ function ShortcutsSettings() {
|
||||||
<Icon icon={icon} />
|
<Icon icon={icon} />
|
||||||
<span class="shortcut-text">
|
<span class="shortcut-text">
|
||||||
<AsyncText>{title}</AsyncText>
|
<AsyncText>{title}</AsyncText>
|
||||||
|
{subtitle && (
|
||||||
|
<>
|
||||||
|
{' '}
|
||||||
|
<small class="ib insignificant">{subtitle}</small>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</span>
|
</span>
|
||||||
<span class="shortcut-actions">
|
<span class="shortcut-actions">
|
||||||
<button
|
<button
|
||||||
|
@ -468,13 +486,17 @@ function ShortcutForm({
|
||||||
</label>
|
</label>
|
||||||
</p>
|
</p>
|
||||||
{TYPE_PARAMS[currentType]?.map?.(
|
{TYPE_PARAMS[currentType]?.map?.(
|
||||||
({ text, name, type, placeholder, pattern }) => {
|
({ text, name, type, placeholder, pattern, notRequired }) => {
|
||||||
if (currentType === 'list') {
|
if (currentType === 'list') {
|
||||||
return (
|
return (
|
||||||
<p>
|
<p>
|
||||||
<label>
|
<label>
|
||||||
<span>List</span>
|
<span>List</span>
|
||||||
<select name="id" required disabled={disabled}>
|
<select
|
||||||
|
name="id"
|
||||||
|
required={!notRequired}
|
||||||
|
disabled={disabled}
|
||||||
|
>
|
||||||
{lists.map((list) => (
|
{lists.map((list) => (
|
||||||
<option value={list.id}>{list.title}</option>
|
<option value={list.id}>{list.title}</option>
|
||||||
))}
|
))}
|
||||||
|
@ -492,7 +514,7 @@ function ShortcutForm({
|
||||||
type={type}
|
type={type}
|
||||||
name={name}
|
name={name}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
required={type === 'text'}
|
required={type === 'text' && !notRequired}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
list={
|
list={
|
||||||
currentType === 'hashtag'
|
currentType === 'hashtag'
|
||||||
|
|
|
@ -134,6 +134,14 @@ shortcuts .tab-bar[hidden] {
|
||||||
#app[data-shortcuts-view-mode='tab-menu-bar'] .deck-container {
|
#app[data-shortcuts-view-mode='tab-menu-bar'] .deck-container {
|
||||||
padding-bottom: 52px;
|
padding-bottom: 52px;
|
||||||
}
|
}
|
||||||
|
#shortcuts .tab-bar li a.has-subtitle .icon,
|
||||||
|
#shortcuts .tab-bar li a.has-subtitle .icon svg {
|
||||||
|
width: 14px !important;
|
||||||
|
height: 14px !important;
|
||||||
|
}
|
||||||
|
#shortcuts .tab-bar li a span {
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 40em) {
|
@media (min-width: 40em) {
|
||||||
|
@ -172,6 +180,10 @@ shortcuts .tab-bar[hidden] {
|
||||||
height: 44px;
|
height: 44px;
|
||||||
gap: 4px;
|
gap: 4px;
|
||||||
}
|
}
|
||||||
|
#shortcuts .tab-bar li a span {
|
||||||
|
text-align: left;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
#app:has(#home-page):not(:has(#home-page ~ .deck-container)):has(
|
#app:has(#home-page):not(:has(#home-page ~ .deck-container)):has(
|
||||||
header[hidden]
|
header[hidden]
|
||||||
)
|
)
|
||||||
|
|
|
@ -30,7 +30,7 @@ function Shortcuts() {
|
||||||
.map((pin, i) => {
|
.map((pin, i) => {
|
||||||
const { type, ...data } = pin;
|
const { type, ...data } = pin;
|
||||||
if (!SHORTCUTS_META[type]) return null;
|
if (!SHORTCUTS_META[type]) return null;
|
||||||
let { id, path, title, icon } = SHORTCUTS_META[type];
|
let { id, path, title, subtitle, icon } = SHORTCUTS_META[type];
|
||||||
|
|
||||||
if (typeof id === 'function') {
|
if (typeof id === 'function') {
|
||||||
id = id(data, i);
|
id = id(data, i);
|
||||||
|
@ -41,6 +41,9 @@ function Shortcuts() {
|
||||||
if (typeof title === 'function') {
|
if (typeof title === 'function') {
|
||||||
title = title(data, i);
|
title = title(data, i);
|
||||||
}
|
}
|
||||||
|
if (typeof subtitle === 'function') {
|
||||||
|
subtitle = subtitle(data, i);
|
||||||
|
}
|
||||||
if (typeof icon === 'function') {
|
if (typeof icon === 'function') {
|
||||||
icon = icon(data, i);
|
icon = icon(data, i);
|
||||||
}
|
}
|
||||||
|
@ -49,6 +52,7 @@ function Shortcuts() {
|
||||||
id,
|
id,
|
||||||
path,
|
path,
|
||||||
title,
|
title,
|
||||||
|
subtitle,
|
||||||
icon,
|
icon,
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
|
@ -73,35 +77,44 @@ function Shortcuts() {
|
||||||
{snapStates.settings.shortcutsViewMode === 'tab-menu-bar' ? (
|
{snapStates.settings.shortcutsViewMode === 'tab-menu-bar' ? (
|
||||||
<nav class="tab-bar">
|
<nav class="tab-bar">
|
||||||
<ul>
|
<ul>
|
||||||
{formattedShortcuts.map(({ id, path, title, icon }, i) => {
|
{formattedShortcuts.map(
|
||||||
return (
|
({ id, path, title, subtitle, icon }, i) => {
|
||||||
<li key={i + title}>
|
return (
|
||||||
<Link
|
<li key={i + title}>
|
||||||
to={path}
|
<Link
|
||||||
onClick={(e) => {
|
class={subtitle ? 'has-subtitle' : ''}
|
||||||
if (e.target.classList.contains('is-active')) {
|
to={path}
|
||||||
e.preventDefault();
|
onClick={(e) => {
|
||||||
const page = document.getElementById(`${id}-page`);
|
if (e.target.classList.contains('is-active')) {
|
||||||
console.log(id, page);
|
e.preventDefault();
|
||||||
if (page) {
|
const page = document.getElementById(`${id}-page`);
|
||||||
page.scrollTop = 0;
|
console.log(id, page);
|
||||||
const updatesButton =
|
if (page) {
|
||||||
page.querySelector('.updates-button');
|
page.scrollTop = 0;
|
||||||
if (updatesButton) {
|
const updatesButton =
|
||||||
updatesButton.click();
|
page.querySelector('.updates-button');
|
||||||
|
if (updatesButton) {
|
||||||
|
updatesButton.click();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}}
|
||||||
}}
|
>
|
||||||
>
|
<Icon icon={icon} size="xl" alt={title} />
|
||||||
<Icon icon={icon} size="xl" alt={title} />
|
<span>
|
||||||
<span>
|
<AsyncText>{title}</AsyncText>
|
||||||
<AsyncText>{title}</AsyncText>
|
{subtitle && (
|
||||||
</span>
|
<>
|
||||||
</Link>
|
<br />
|
||||||
</li>
|
<small>{subtitle}</small>
|
||||||
);
|
</>
|
||||||
})}
|
)}
|
||||||
|
</span>
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
)}
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
) : (
|
) : (
|
||||||
|
@ -132,12 +145,20 @@ function Shortcuts() {
|
||||||
</button>
|
</button>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{formattedShortcuts.map(({ path, title, icon }, i) => {
|
{formattedShortcuts.map(({ path, title, subtitle, icon }, i) => {
|
||||||
return (
|
return (
|
||||||
<MenuLink to={path} key={i + title} class="glass-menu-item">
|
<MenuLink to={path} key={i + title} class="glass-menu-item">
|
||||||
<Icon icon={icon} size="l" />{' '}
|
<Icon icon={icon} size="l" />{' '}
|
||||||
<span class="menu-grow">
|
<span class="menu-grow">
|
||||||
<AsyncText>{title}</AsyncText>
|
<span>
|
||||||
|
<AsyncText>{title}</AsyncText>
|
||||||
|
</span>
|
||||||
|
{subtitle && (
|
||||||
|
<>
|
||||||
|
{' '}
|
||||||
|
<small class="more-insignificant">{subtitle}</small>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</span>
|
</span>
|
||||||
<span class="menu-shortcut hide-until-focus-visible">
|
<span class="menu-shortcut hide-until-focus-visible">
|
||||||
{i + 1}
|
{i + 1}
|
||||||
|
|
|
@ -32,8 +32,10 @@ function Hashtags(props) {
|
||||||
hashtags.sort();
|
hashtags.sort();
|
||||||
hashtag = hashtags[0];
|
hashtag = hashtags[0];
|
||||||
|
|
||||||
const { masto, instance } = api({ instance: params.instance });
|
const { masto, instance, authenticated } = api({
|
||||||
const { authenticated } = api();
|
instance: props?.instance || params.instance,
|
||||||
|
});
|
||||||
|
const { authenticated: currentAuthenticated } = api();
|
||||||
const hashtagTitle = hashtags.map((t) => `#${t}`).join(' ');
|
const hashtagTitle = hashtags.map((t) => `#${t}`).join(' ');
|
||||||
const title = instance ? `${hashtagTitle} on ${instance}` : hashtagTitle;
|
const title = instance ? `${hashtagTitle} on ${instance}` : hashtagTitle;
|
||||||
useTitle(title, `/:instance?/t/:hashtag`);
|
useTitle(title, `/:instance?/t/:hashtag`);
|
||||||
|
@ -99,7 +101,7 @@ function Hashtags(props) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Timeline
|
<Timeline
|
||||||
key={hashtagTitle}
|
key={instance + hashtagTitle}
|
||||||
title={title}
|
title={title}
|
||||||
titleComponent={
|
titleComponent={
|
||||||
!!instance && (
|
!!instance && (
|
||||||
|
@ -232,6 +234,7 @@ function Hashtags(props) {
|
||||||
{hashtags.map((t, i) => (
|
{hashtags.map((t, i) => (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
key={t}
|
key={t}
|
||||||
|
disabled={hashtags.length === 1}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
hashtags.splice(i, 1);
|
hashtags.splice(i, 1);
|
||||||
hashtags.sort();
|
hashtags.sort();
|
||||||
|
@ -252,7 +255,7 @@ function Hashtags(props) {
|
||||||
</MenuGroup>
|
</MenuGroup>
|
||||||
<MenuDivider />
|
<MenuDivider />
|
||||||
<MenuItem
|
<MenuItem
|
||||||
disabled={!authenticated}
|
disabled={!currentAuthenticated}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
const shortcut = {
|
const shortcut = {
|
||||||
type: 'hashtag',
|
type: 'hashtag',
|
||||||
|
@ -281,6 +284,23 @@ function Hashtags(props) {
|
||||||
>
|
>
|
||||||
<Icon icon="shortcut" /> <span>Add to Shorcuts</span>
|
<Icon icon="shortcut" /> <span>Add to Shorcuts</span>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
<MenuItem
|
||||||
|
onClick={() => {
|
||||||
|
let newInstance = prompt(
|
||||||
|
'Enter a new instance e.g. "mastodon.social"',
|
||||||
|
);
|
||||||
|
if (!/\./.test(newInstance)) {
|
||||||
|
if (newInstance) alert('Invalid instance');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (newInstance) {
|
||||||
|
newInstance = newInstance.toLowerCase().trim();
|
||||||
|
navigate(`/${newInstance}/t/${hashtags.join('+')}`);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Icon icon="bus" /> <span>Go to another instance…</span>
|
||||||
|
</MenuItem>
|
||||||
</Menu>
|
</Menu>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
Loading…
Add table
Reference in a new issue