feat(links): new external link implementation

This commit is contained in:
SabreCat
2023-03-22 18:06:53 -05:00
parent 008579363c
commit ca1200b689
8 changed files with 75 additions and 20 deletions

View File

@@ -322,6 +322,7 @@ import omit from 'lodash/omit';
import { v4 as uuid } from 'uuid'; import { v4 as uuid } from 'uuid';
import { userStateMixin } from '../../mixins/userState'; import { userStateMixin } from '../../mixins/userState';
import externalLinks from '../../mixins/externalLinks';
import memberSearchDropdown from '@/components/members/memberSearchDropdown'; import memberSearchDropdown from '@/components/members/memberSearchDropdown';
import closeChallengeModal from './closeChallengeModal'; import closeChallengeModal from './closeChallengeModal';
import Column from '../tasks/column'; import Column from '../tasks/column';
@@ -358,7 +359,7 @@ export default {
userLink, userLink,
groupLink, groupLink,
}, },
mixins: [challengeMemberSearchMixin, userStateMixin], mixins: [challengeMemberSearchMixin, externalLinks, userStateMixin],
props: ['challengeId'], props: ['challengeId'],
data () { data () {
return { return {
@@ -414,6 +415,10 @@ export default {
mounted () { mounted () {
if (!this.searchId) this.searchId = this.challengeId; if (!this.searchId) this.searchId = this.challengeId;
if (!this.challenge._id) this.loadChallenge(); if (!this.challenge._id) this.loadChallenge();
this.handleExternalLinks();
},
updated () {
this.handleExternalLinks();
}, },
async beforeRouteUpdate (to, from, next) { async beforeRouteUpdate (to, from, next) {
this.searchId = to.params.challengeId; this.searchId = to.params.challengeId;

View File

@@ -120,6 +120,7 @@ import { mapState } from '@/libs/store';
import Sidebar from './sidebar'; import Sidebar from './sidebar';
import ChallengeItem from './challengeItem'; import ChallengeItem from './challengeItem';
import challengeModal from './challengeModal'; import challengeModal from './challengeModal';
import externalLinks from '@/mixins/externalLinks';
import challengeUtilities from '@/mixins/challengeUtilities'; import challengeUtilities from '@/mixins/challengeUtilities';
import positiveIcon from '@/assets/svg/positive.svg'; import positiveIcon from '@/assets/svg/positive.svg';
@@ -131,7 +132,7 @@ export default {
challengeModal, challengeModal,
MugenScroll, MugenScroll,
}, },
mixins: [challengeUtilities], mixins: [challengeUtilities, externalLinks],
data () { data () {
return { return {
loading: true, loading: true,
@@ -177,6 +178,10 @@ export default {
section: this.$t('challenges'), section: this.$t('challenges'),
}); });
this.loadChallenges(); this.loadChallenges();
this.handleExternalLinks();
},
updated () {
this.handleExternalLinks();
}, },
methods: { methods: {
updateSearch (eventData) { updateSearch (eventData) {

View File

@@ -81,6 +81,8 @@ import challengeModal from './challengeModal';
import { mapState } from '@/libs/store'; import { mapState } from '@/libs/store';
import markdownDirective from '@/directives/markdown'; import markdownDirective from '@/directives/markdown';
import externalLinks from '../../mixins/externalLinks';
import challengeItem from './challengeItem'; import challengeItem from './challengeItem';
import challengeIcon from '@/assets/svg/challenge.svg'; import challengeIcon from '@/assets/svg/challenge.svg';
@@ -92,6 +94,7 @@ export default {
directives: { directives: {
markdown: markdownDirective, markdown: markdownDirective,
}, },
mixins: [externalLinks],
props: ['group'], props: ['group'],
data () { data () {
return { return {
@@ -118,6 +121,10 @@ export default {
}, },
mounted () { mounted () {
this.loadChallenges(); this.loadChallenges();
this.handleExternalLinks();
},
updated () {
this.handleExternalLinks();
}, },
methods: { methods: {
async loadChallenges () { async loadChallenges () {

View File

@@ -145,6 +145,7 @@ import Sidebar from './sidebar';
import ChallengeItem from './challengeItem'; import ChallengeItem from './challengeItem';
import challengeModal from './challengeModal'; import challengeModal from './challengeModal';
import challengeUtilities from '@/mixins/challengeUtilities'; import challengeUtilities from '@/mixins/challengeUtilities';
import externalLinks from '@/mixins/externalLinks';
import challengeIcon from '@/assets/svg/challenge.svg'; import challengeIcon from '@/assets/svg/challenge.svg';
import positiveIcon from '@/assets/svg/positive.svg'; import positiveIcon from '@/assets/svg/positive.svg';
@@ -156,7 +157,7 @@ export default {
challengeModal, challengeModal,
MugenScroll, MugenScroll,
}, },
mixins: [challengeUtilities], mixins: [challengeUtilities, externalLinks],
data () { data () {
return { return {
icons: Object.freeze({ icons: Object.freeze({
@@ -203,6 +204,10 @@ export default {
section: this.$t('challenges'), section: this.$t('challenges'),
}); });
this.loadChallenges(); this.loadChallenges();
this.handleExternalLinks();
},
updated () {
this.handleExternalLinks();
}, },
methods: { methods: {
updateSearch (eventData) { updateSearch (eventData) {

View File

@@ -87,6 +87,8 @@
<script> <script>
import debounce from 'lodash/debounce'; import debounce from 'lodash/debounce';
import externalLinks from '../../mixins/externalLinks';
import autocomplete from '../chat/autoComplete'; import autocomplete from '../chat/autoComplete';
import communityGuidelines from './communityGuidelines'; import communityGuidelines from './communityGuidelines';
import chatMessage from '../chat/chatMessages'; import chatMessage from '../chat/chatMessages';
@@ -103,6 +105,7 @@ export default {
communityGuidelines, communityGuidelines,
chatMessage, chatMessage,
}, },
mixins: [externalLinks],
props: ['label', 'group', 'placeholder'], props: ['label', 'group', 'placeholder'],
data () { data () {
return { return {
@@ -133,6 +136,9 @@ export default {
mounted () { mounted () {
this.textbox = this.$refs['user-entry']; this.textbox = this.$refs['user-entry'];
}, },
updated () {
this.handleExternalLinks();
},
methods: { methods: {
// https://medium.com/@_jh3y/how-to-where-s-the-caret-getting-the-xy-position-of-the-caret-a24ba372990a // https://medium.com/@_jh3y/how-to-where-s-the-caret-getting-the-xy-position-of-the-caret-a24ba372990a
getCoord (e, text) { getCoord (e, text) {

View File

@@ -355,6 +355,7 @@ import Task from './task';
import ClearCompletedTodos from './clearCompletedTodos'; import ClearCompletedTodos from './clearCompletedTodos';
import buyMixin from '@/mixins/buy'; import buyMixin from '@/mixins/buy';
import sync from '@/mixins/sync'; import sync from '@/mixins/sync';
import externalLinks from '@/mixins/externalLinks';
import { mapState, mapActions, mapGetters } from '@/libs/store'; import { mapState, mapActions, mapGetters } from '@/libs/store';
import shopItem from '../shops/shopItem'; import shopItem from '../shops/shopItem';
import BuyQuestModal from '@/components/shops/quests/buyQuestModal.vue'; import BuyQuestModal from '@/components/shops/quests/buyQuestModal.vue';
@@ -384,7 +385,7 @@ export default {
shopItem, shopItem,
draggable, draggable,
}, },
mixins: [buyMixin, notifications, sync], mixins: [buyMixin, notifications, sync, externalLinks],
// @TODO Set default values for props // @TODO Set default values for props
// allows for better control of props values // allows for better control of props values
// allows for better control of where this component is called // allows for better control of where this component is called
@@ -534,6 +535,10 @@ export default {
if (this.activeFilter.label !== 'complete2') return; if (this.activeFilter.label !== 'complete2') return;
this.loadCompletedTodos(); this.loadCompletedTodos();
}); });
this.handleExternalLinks();
},
updated () {
this.handleExternalLinks();
}, },
beforeDestroy () { beforeDestroy () {
this.$root.$off('buyModal::boughtItem'); this.$root.$off('buyModal::boughtItem');

View File

@@ -9,21 +9,5 @@ export default function markdown (el, { value, oldValue }) {
el.innerHTML = ''; el.innerHTML = '';
} }
const allLinks = el.getElementsByTagName('a');
for (let i = 0; i < allLinks.length; i += 1) {
const link = allLinks[i];
link.addEventListener('click', e => {
if (e.ctrlKey) {
return;
}
e.stopPropagation();
e.preventDefault();
window.externalLink(link.href);
});
}
el.classList.add('markdown'); el.classList.add('markdown');
} }

View File

@@ -0,0 +1,38 @@
import some from 'lodash/some';
export default {
data () {
return {
trustedDomains: [
'https://habitica.com',
'http://localhost',
'https://tools.habitica.com',
'https://translate.habitica.com',
],
};
},
methods: {
handleExternalLinks () {
const allLinks = document.getElementsByTagName('a');
for (let i = 0; i < allLinks.length; i += 1) {
const link = allLinks[i];
if ((link.classList.value.indexOf('external-link') === -1)
&& link.href.slice(0, 4) === 'http'
&& !some(this.trustedDomains, domain => link.href.indexOf(domain) === 0)) {
link.classList.add('external-link');
link.addEventListener('click', e => {
if (e.ctrlKey) {
return;
}
e.stopPropagation();
e.preventDefault();
window.externalLink(link.href);
});
}
}
},
},
};