mirror of
https://github.com/romancm/gamebrary
synced 2024-11-12 22:47:14 +00:00
Improve game highlighting
This commit is contained in:
parent
af3f161022
commit
02d5836ae1
17 changed files with 123 additions and 49 deletions
|
@ -19,6 +19,7 @@
|
|||
import { mapState, mapGetters } from 'vuex';
|
||||
import AddKanbanList from '@/components/Board/AddKanbanList';
|
||||
import KanbanList from '@/components/Lists/KanbanList';
|
||||
import { HIGHLIGHTED_GAME_TIMEOUT } from '@/constants'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
@ -27,7 +28,7 @@ export default {
|
|||
},
|
||||
|
||||
mounted() {
|
||||
if (this.highlightedGame) this.highlightGame();
|
||||
if (this.highlightedGame) this.scrollToGame();
|
||||
},
|
||||
|
||||
computed: {
|
||||
|
@ -40,7 +41,7 @@ export default {
|
|||
},
|
||||
|
||||
methods: {
|
||||
highlightGame() {
|
||||
scrollToGame() {
|
||||
const lists = Object.values(this.$refs);
|
||||
|
||||
lists.forEach(([list], index) => {
|
||||
|
@ -55,7 +56,7 @@ export default {
|
|||
|
||||
setTimeout(() => {
|
||||
this.$store.commit('SET_HIGHLIGHTED_GAME', null);
|
||||
}, 5000);
|
||||
}, HIGHLIGHTED_GAME_TIMEOUT);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
<!-- <router-link :to="{ name: 'board', params: { id: board.id } }"></router-link> -->
|
||||
<!-- TODO: make mini boards links so you can cmd click them -->
|
||||
<template lang="html">
|
||||
<b-card
|
||||
|
@ -33,7 +34,6 @@
|
|||
<component
|
||||
:is="miniBoardComponent"
|
||||
:board="formattedBoard"
|
||||
:gameId="gameId"
|
||||
/>
|
||||
</div>
|
||||
</b-card>
|
||||
|
@ -50,7 +50,6 @@ import TierMiniBoard from '@/components/MiniBoards/TierMiniBoard';
|
|||
export default {
|
||||
props: {
|
||||
board: Object,
|
||||
gameId: Number,
|
||||
thumbnail: Boolean,
|
||||
},
|
||||
|
||||
|
@ -73,7 +72,7 @@ export default {
|
|||
},
|
||||
|
||||
computed: {
|
||||
...mapState(['cachedGames']),
|
||||
...mapState(['cachedGames', 'game']),
|
||||
...mapGetters(['darkTheme']),
|
||||
|
||||
miniBoardComponent() {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
<div class="standard-board pb-5">
|
||||
<StandardList
|
||||
v-for="(list, listIndex) in board.lists"
|
||||
:ref="`list-${listIndex}`"
|
||||
:key="list.id"
|
||||
:listIndex="listIndex"
|
||||
:list="list"
|
||||
|
@ -12,14 +13,14 @@
|
|||
<script>
|
||||
import { mapState } from 'vuex';
|
||||
import StandardList from '@/components/Lists/StandardList';
|
||||
|
||||
import { HIGHLIGHTED_GAME_TIMEOUT } from '@/constants';
|
||||
export default {
|
||||
components: {
|
||||
StandardList,
|
||||
},
|
||||
|
||||
computed: {
|
||||
...mapState(['board']),
|
||||
...mapState(['board', 'highlightedGame']),
|
||||
|
||||
list() {
|
||||
const [firstList] = this.board?.lists;
|
||||
|
@ -38,9 +39,30 @@ export default {
|
|||
|
||||
mounted() {
|
||||
if (this.needsFlattening) this.flattenAndSaveBoard();
|
||||
if (this.highlightedGame) this.highlightGame();
|
||||
},
|
||||
|
||||
methods: {
|
||||
highlightGame() {
|
||||
const lists = Object.values(this.$refs);
|
||||
|
||||
lists.forEach(([list], index) => {
|
||||
const [gameRef] = list.$refs[`${index}-${this.highlightedGame}`];
|
||||
|
||||
if (gameRef) {
|
||||
console.log('gameRef', gameRef);
|
||||
|
||||
setTimeout(() => {
|
||||
gameRef?.$el.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
||||
}, index * 1000);
|
||||
}
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
this.$store.commit('SET_HIGHLIGHTED_GAME', null);
|
||||
}, HIGHLIGHTED_GAME_TIMEOUT);
|
||||
},
|
||||
|
||||
async flattenAndSaveBoard() {
|
||||
const mergedGamesList = [...new Set(this.board?.lists?.map(({ games }) => games)?.flat())];
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
<TierList
|
||||
v-for="(list, listIndex) in board.lists"
|
||||
:list="list"
|
||||
:ref="`tier-${listIndex}`"
|
||||
:allGames="allGames"
|
||||
:listIndex="listIndex"
|
||||
:key="listIndex"
|
||||
|
@ -20,6 +21,7 @@
|
|||
import { mapState, mapGetters } from 'vuex';
|
||||
import AddTier from '@/components/Board/AddTier';
|
||||
import TierList from '@/components/Lists/TierList';
|
||||
import { HIGHLIGHTED_GAME_TIMEOUT } from '@/constants';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
@ -27,8 +29,12 @@ export default {
|
|||
AddTier,
|
||||
},
|
||||
|
||||
mounted() {
|
||||
if (this.highlightedGame) this.highlightGame();
|
||||
},
|
||||
|
||||
computed: {
|
||||
...mapState(['board']),
|
||||
...mapState(['board', 'highlightedGame']),
|
||||
...mapGetters(['isBoardOwner', 'darkTheme']),
|
||||
|
||||
allGames() {
|
||||
|
@ -41,6 +47,24 @@ export default {
|
|||
},
|
||||
|
||||
methods: {
|
||||
highlightGame() {
|
||||
const lists = Object.values(this.$refs);
|
||||
|
||||
lists.forEach(([list], index) => {
|
||||
const [gameRef] = list.$refs[`${index}-${this.highlightedGame}`];
|
||||
|
||||
if (gameRef) {
|
||||
setTimeout(() => {
|
||||
gameRef?.$el.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
||||
}, index * 1000);
|
||||
}
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
this.$store.commit('SET_HIGHLIGHTED_GAME', null);
|
||||
}, HIGHLIGHTED_GAME_TIMEOUT);
|
||||
},
|
||||
|
||||
async selectGame(gameId) {
|
||||
const board = JSON.parse(JSON.stringify(this.board));
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
v-for="board in boardsWithGame"
|
||||
:key="board.id"
|
||||
:board="board"
|
||||
:gameId="game.id"
|
||||
class="mb-3"
|
||||
@click.native="handleBoardClick(board.id)"
|
||||
/>
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
vertical,
|
||||
small,
|
||||
slim,
|
||||
highlighted: highlightedGame === gameId,
|
||||
'semi-transparent': transparencyEnabled,
|
||||
},
|
||||
darkTheme ? 'dark text-light' : 'light',
|
||||
|
@ -155,7 +156,7 @@ export default {
|
|||
},
|
||||
|
||||
computed: {
|
||||
...mapState(['settings', 'cachedGames', 'tags', 'notes', 'progresses', 'board', 'games', 'user']),
|
||||
...mapState(['settings', 'cachedGames', 'tags', 'notes', 'progresses', 'board', 'games', 'user', 'highlightedGame']),
|
||||
...mapGetters(['isRTL', 'darkTheme', 'transparencyEnabled']),
|
||||
|
||||
game() {
|
||||
|
@ -226,6 +227,10 @@ export default {
|
|||
transition: background-color 300ms linear;
|
||||
padding: 0.5rem;
|
||||
|
||||
&.highlighted {
|
||||
border: 3px dotted var(--danger);
|
||||
}
|
||||
|
||||
&.slim {
|
||||
padding: 0;
|
||||
grid-gap: 0;
|
||||
|
|
|
@ -93,7 +93,6 @@
|
|||
:small="list.smallCover"
|
||||
:hide-cover="list.hideCover"
|
||||
:hide-title="list.hideTitle"
|
||||
:class="{ 'highlighted': highlightedGame == gameId }"
|
||||
@click.native="openGame(gameId, list)"
|
||||
/>
|
||||
</draggable>
|
||||
|
@ -118,7 +117,13 @@ import draggable from 'vuedraggable';
|
|||
import GameCard from '@/components/GameCard';
|
||||
import slugify from 'slugify'
|
||||
import orderby from 'lodash.orderby';
|
||||
import { SORT_TYPE_ALPHABETICALLY, SORT_TYPE_RATING, SORT_TYPE_PROGRESS } from '@/constants';
|
||||
import {
|
||||
SORT_TYPE_ALPHABETICALLY,
|
||||
SORT_TYPE_RATING,
|
||||
SORT_TYPE_PROGRESS,
|
||||
HIGHLIGHTED_GAME_TIMEOUT
|
||||
} from '@/constants';
|
||||
|
||||
import { mapState, mapGetters } from 'vuex';
|
||||
|
||||
export default {
|
||||
|
@ -154,14 +159,14 @@ export default {
|
|||
},
|
||||
|
||||
computed: {
|
||||
...mapState(['cachedGames', 'dragging', 'progresses', 'board', 'user', 'settings', 'highlightedGame']),
|
||||
...mapState(['cachedGames', 'dragging', 'progresses', 'board', 'user', 'settings']),
|
||||
...mapGetters(['isBoardOwner', 'darkTheme', 'transparencyEnabled']),
|
||||
|
||||
sortMessage() {
|
||||
if (this.sortBy === SORT_TYPE_ALPHABETICALLY) return 'List sorted alphabetically'
|
||||
if (this.sortBy === SORT_TYPE_RATING) return 'List sorted by rating'
|
||||
if (this.sortBy === SORT_TYPE_PROGRESS) return 'List sorted by progress'
|
||||
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
|
@ -265,7 +270,7 @@ export default {
|
|||
|
||||
setTimeout(() => {
|
||||
this.$store.commit('SET_HIGHLIGHTED_GAME', null);
|
||||
}, 5000);
|
||||
}, HIGHLIGHTED_GAME_TIMEOUT);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -377,10 +382,6 @@ export default {
|
|||
.list-settings {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.highlighted {
|
||||
outline: 3px dashed var(--primary);
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss" rel="stylesheet/scss">
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
v-for="(game, index) in listGames"
|
||||
:key="index"
|
||||
:list="list"
|
||||
:ref="`${listIndex}-${game.id}`"
|
||||
:game-id="game.id"
|
||||
:ranked="board.ranked"
|
||||
:rank="index + 1"
|
||||
|
|
|
@ -64,11 +64,12 @@
|
|||
:group="{ name: 'games' }"
|
||||
@end="dragEnd"
|
||||
@start="dragStart"
|
||||
>
|
||||
>
|
||||
<GameCard
|
||||
v-for="gameId in list.games"
|
||||
:key="gameId"
|
||||
:game-id="gameId"
|
||||
:ref="`${listIndex}-${gameId}`"
|
||||
hide-title
|
||||
hide-tags
|
||||
hide-notes
|
||||
|
|
|
@ -12,10 +12,14 @@
|
|||
<div
|
||||
v-for="(game, index) in list.games"
|
||||
:key="index"
|
||||
style="width: 60px"
|
||||
style="width: 60px;"
|
||||
class="p-1 d-flex"
|
||||
:class="[
|
||||
gameId && game.id === gameId ? 'bg-danger' : darkTheme ? 'border-black bg-dark' : 'border-light bg-white',
|
||||
game.id === currentGameId
|
||||
? 'bg-danger'
|
||||
: darkTheme
|
||||
? 'border-black bg-dark'
|
||||
: 'border-light bg-white',
|
||||
{
|
||||
'border-bottom' : index !== list.games.length - 1,
|
||||
}
|
||||
|
@ -24,7 +28,7 @@
|
|||
<b-avatar
|
||||
style="border-radius: 4px !important"
|
||||
text=" "
|
||||
:src="gameId && game.src && game.id === gameId ? game.src : showGameThumbnails && game.src ? game.src : null"
|
||||
:src="currentGameId && game.src && game.id === currentGameId ? game.src : showGameThumbnails && game.src ? game.src : null"
|
||||
v-b-tooltip.hover
|
||||
:variant="darkTheme ? 'black' : 'light'"
|
||||
size="24"
|
||||
|
@ -36,30 +40,23 @@
|
|||
<div
|
||||
v-else
|
||||
class="rounded overflow-hidden"
|
||||
style="height: 22px; width: 60px;"
|
||||
style="height: 28px; width: 60px;"
|
||||
/>
|
||||
</b-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import { mapGetters, mapState } from 'vuex';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
gameId: Number,
|
||||
board: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
// Your data properties here
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
highlightGame(gameId) {
|
||||
this.$store.commit('SET_HIGHLIGHTED_GAME', gameId);
|
||||
|
@ -68,14 +65,13 @@ export default {
|
|||
|
||||
computed: {
|
||||
...mapGetters(['darkTheme', 'showGameThumbnails']),
|
||||
},
|
||||
...mapState(['game', 'routeName']),
|
||||
|
||||
mounted() {
|
||||
// Code to run when the component is mounted
|
||||
currentGameId() {
|
||||
return this.routeName === 'game'
|
||||
? this.game?.id
|
||||
: null;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* Your CSS styles here */
|
||||
</style>
|
||||
|
|
|
@ -27,7 +27,14 @@
|
|||
<div
|
||||
v-for="(game, index) in firstList.games"
|
||||
:key="index"
|
||||
:class="[darkTheme ? 'border-black bg-dark' : 'border-light bg-white', { 'border-bottom': index !== firstList.games.length - 1 }]"
|
||||
:class="[
|
||||
currentGameId == game.id
|
||||
? 'border bg-danger border-danger'
|
||||
: darkTheme
|
||||
? 'border-black bg-dark'
|
||||
: 'border-light bg-white',
|
||||
{ 'border-bottom': index !== firstList.games.length - 1 },
|
||||
]"
|
||||
class=""
|
||||
>
|
||||
<b-avatar
|
||||
|
@ -55,7 +62,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import { mapGetters, mapState } from 'vuex';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
|
@ -63,11 +70,17 @@ export default {
|
|||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
gameId: Number,
|
||||
},
|
||||
|
||||
computed: {
|
||||
...mapGetters(['darkTheme', 'showGameThumbnails']),
|
||||
...mapState(['routeName', 'game']),
|
||||
|
||||
currentGameId() {
|
||||
return this.routeName === 'game'
|
||||
? this.game?.id
|
||||
: null;
|
||||
},
|
||||
|
||||
isGrid() {
|
||||
return this.board?.grid;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<template>
|
||||
<div>
|
||||
<pre>{{ currentGameId || 'not game page' }}</pre>
|
||||
<div
|
||||
class="d-flex mx-2"
|
||||
v-for="tier in board.lists"
|
||||
|
@ -22,6 +23,7 @@
|
|||
square
|
||||
:src="showGameThumbnails ? game.src : null"
|
||||
style="margin-left: 4px; border-radius: 4px !important;"
|
||||
:class="currentGameId === game.id ? 'border border-danger' : null"
|
||||
size="20"
|
||||
/>
|
||||
</div>
|
||||
|
@ -29,7 +31,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import { mapGetters, mapState } from 'vuex';
|
||||
export default {
|
||||
props: {
|
||||
board: {
|
||||
|
@ -41,6 +43,13 @@ export default {
|
|||
|
||||
computed: {
|
||||
...mapGetters(['darkTheme', 'showGameThumbnails']),
|
||||
...mapState(['routeName', 'game']),
|
||||
|
||||
currentGameId() {
|
||||
return this.routeName === 'game'
|
||||
? this.game?.id
|
||||
: null;
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
|
|
@ -28,6 +28,7 @@ export const SORT_TYPE_RATING = 'rating';
|
|||
export const SORT_TYPE_PROGRESS = 'progress';
|
||||
|
||||
export const MAX_QUERY_LIMIT = 500;
|
||||
export const HIGHLIGHTED_GAME_TIMEOUT = 5000; // set back to 5000
|
||||
|
||||
export const BOARD_TYPES = [
|
||||
{ text: 'Kanban', value: BOARD_TYPE_KANBAN },
|
||||
|
|
|
@ -537,10 +537,12 @@ export default {
|
|||
},
|
||||
|
||||
LOAD_RELEASES({ commit }) {
|
||||
// TODO: use await async
|
||||
return new Promise((resolve, reject) => {
|
||||
axios
|
||||
.get("https://api.github.com/repos/romancm/gamebrary/releases")
|
||||
.then(({ data }) => {
|
||||
console.log('releases', data);
|
||||
// const [latestRelease] = data;
|
||||
// const latestReleaseVersion = latestRelease && latestRelease.tag_name;
|
||||
// const lastReleaseSeenByUser = this.settings?.release || null;
|
||||
|
|
|
@ -15,8 +15,8 @@ import linkifyHtml from 'linkify-html';
|
|||
|
||||
export default {
|
||||
latestRelease: ({ releases }) => releases?.[0]?.tag_name || 'v1',
|
||||
darkTheme: ({ route, board, settings }) => {
|
||||
const boardOverride = route === 'board' && board?.darkTheme;
|
||||
darkTheme: ({ routeName, board, settings }) => {
|
||||
const boardOverride = routeName === 'board' && board?.darkTheme;
|
||||
|
||||
return settings?.darkTheme || boardOverride || false
|
||||
},
|
||||
|
|
|
@ -161,8 +161,8 @@ export default {
|
|||
Vue.set(state.game, 'news', news);
|
||||
},
|
||||
|
||||
SET_ROUTE(state, route) {
|
||||
state.route = route;
|
||||
SET_ROUTE(state, routeName) {
|
||||
state.routeName = routeName;
|
||||
},
|
||||
|
||||
APPEND_WIKIPEDIA_GAME_DATA(state, data) {
|
||||
|
|
|
@ -26,5 +26,5 @@ export default {
|
|||
gameSelectorData: null,
|
||||
menuOpen: true,
|
||||
editProfileSidebarOpen: false,
|
||||
route: {},
|
||||
routeName: null,
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue