Skip to content

Commit d05122d

Browse files
committed
confirm encounter runner exit menu
1 parent 6eadb72 commit d05122d

3 files changed

Lines changed: 148 additions & 79 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "compcon",
33
"private": true,
4-
"version": "3.0.",
4+
"version": "3.0.6",
55
"scripts": {
66
"dev": "vite",
77
"build": "vue-tsc --noEmit && vite build",

src/features/active_mode/runner/gm/GMEncounterRunner.vue

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,13 +129,40 @@
129129
:selected="selected"
130130
@close="tableDialog = false" />
131131
</v-dialog>
132+
133+
<cc-solo-dialog v-model="leaveDialog"
134+
:close-on-click="false"
135+
title="Exit Active Mode?"
136+
:z-index="9999">
137+
<v-card flat
138+
tile>
139+
140+
<div class="text-center text-text ma-2">
141+
Do you want to save this encounter before exiting?</div>
142+
<v-divider class="my-3" />
143+
<v-card-actions class="pa-0">
144+
<cc-button variant="text"
145+
size="small"
146+
@click="handleLeave('cancel')">Cancel</cc-button>
147+
<v-spacer />
148+
<cc-button color="warning"
149+
size="small"
150+
variant="text"
151+
@click="handleLeave('exit')">Exit Without Saving</cc-button>
152+
<v-spacer />
153+
<cc-button color="accent"
154+
size="small"
155+
@click="handleLeave('save')">Save and Exit</cc-button>
156+
</v-card-actions>
157+
</v-card>
158+
</cc-solo-dialog>
132159
</div>
133160
</template>
134161

135162
<script setup lang="ts">
136163
import { ref, computed, watch, onMounted } from 'vue';
137164
import { useDisplay } from 'vuetify';
138-
import { useRoute } from 'vue-router';
165+
import { useRoute, onBeforeRouteLeave } from 'vue-router';
139166
import { orderBy } from 'lodash-es';
140167
import DeployablePanel from './EncounterPanels/DeployablePanel.vue';
141168
import DoodadPanel from './EncounterPanels/DoodadPanel.vue';
@@ -184,6 +211,8 @@ const route = useRoute();
184211
const selected = ref<any>(null);
185212
const diceDialog = ref(false);
186213
const tableDialog = ref(false);
214+
const leaveDialog = ref(false);
215+
let resolveLeaveDialog: ((value: string) => void) | null = null;
187216
const panel = ref<string | undefined>('encounter-info');
188217
const sort = ref('');
189218
const showLeft = ref(true);
@@ -250,4 +279,28 @@ function selectPanel(p: string) {
250279
panel.value = p;
251280
}
252281
}
282+
283+
function openLeaveDialog(): Promise<string> {
284+
leaveDialog.value = true;
285+
return new Promise((resolve) => {
286+
resolveLeaveDialog = resolve;
287+
});
288+
}
289+
290+
function handleLeave(choice: 'save' | 'exit' | 'cancel') {
291+
leaveDialog.value = false;
292+
resolveLeaveDialog?.(choice);
293+
resolveLeaveDialog = null;
294+
}
295+
296+
onBeforeRouteLeave(async () => {
297+
const choice = await openLeaveDialog();
298+
if (choice === 'save') {
299+
instance.value?.Save();
300+
return true;
301+
} else if (choice === 'exit') {
302+
return true;
303+
}
304+
return false;
305+
});
253306
</script>
Lines changed: 93 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,10 @@
11
<template>
2-
<div
3-
v-if="!sheet"
4-
:key="sheetID"
5-
>
6-
<v-progress-linear
7-
indeterminate
2+
<div v-if="!sheet"
3+
:key="sheetID">
4+
<v-progress-linear indeterminate
85
color="primary"
96
height="20"
10-
class="my-5"
11-
/>
7+
class="my-5" />
128
<div class="text-center text-cc-overline">Loading pilot sheet...</div>
139
</div>
1410
<div v-else>
@@ -18,101 +14,75 @@
1814
<v-container fluid>
1915
<div>
2016
<div v-if="panel && sheet">
21-
<component
22-
:is="panelMap[panel]"
17+
<component :is="panelMap[panel]"
2318
:key="panel"
2419
:combatant="combatant"
2520
:encounter="encounterInstance.Encounter"
2621
:selected="pilot"
2722
:sheet="sheet"
2823
pc
29-
:encounter-instance="encounterInstance"
30-
/>
24+
:encounter-instance="encounterInstance" />
3125
</div>
3226

33-
<v-row
34-
dense
35-
justify="end"
36-
>
27+
<v-row dense
28+
justify="end">
3729
<v-col cols="auto">
38-
<actor-telemetry
39-
:actor="pilot"
40-
:encounter="encounterInstance"
41-
/>
30+
<actor-telemetry :actor="pilot"
31+
:encounter="encounterInstance" />
4232
</v-col>
4333
<v-col cols="auto">
44-
<actor-logs
45-
:actor="pilot"
46-
:encounter="encounterInstance"
47-
/>
34+
<actor-logs :actor="pilot"
35+
:encounter="encounterInstance" />
4836
</v-col>
4937
<v-col cols="auto">
50-
<combat-statblock-export
51-
:actor="pilot"
52-
:encounter="encounterInstance"
53-
/>
38+
<combat-statblock-export :actor="pilot"
39+
:encounter="encounterInstance" />
5440
</v-col>
5541
</v-row>
5642
</div>
5743
</v-container>
5844
</v-main>
5945

60-
<div
61-
style="position: absolute; z-index: 999"
62-
:style="`right: ${showRight ? (mobile ? '60' : '256') : mobile ? '6' : '62'}px; top: 6px`"
63-
>
64-
<cc-button
65-
:icon="showRight ? 'mdi-chevron-double-right' : 'mdi-chevron-double-left'"
46+
<div style="position: absolute; z-index: 999"
47+
:style="`right: ${showRight ? (mobile ? '60' : '256') : mobile ? '6' : '62'}px; top: 6px`">
48+
<cc-button :icon="showRight ? 'mdi-chevron-double-right' : 'mdi-chevron-double-left'"
6649
size="small"
6750
color="primary"
68-
@click="showRight = !showRight"
69-
/>
51+
@click="showRight = !showRight" />
7052
</div>
7153

72-
<v-navigation-drawer
73-
v-if="!mobile"
54+
<v-navigation-drawer v-if="!mobile"
7455
:rail="!showRight"
7556
location="right"
76-
permanent
77-
>
78-
<gm-tool-palette
79-
pc
57+
permanent>
58+
<gm-tool-palette pc
8059
:expanded="showRight"
8160
:selected="panel"
8261
:combatant="combatant"
8362
@select-panel="selectPanel"
8463
@open-dice-roller="diceDialog = true"
85-
@open-table-index="tableDialog = true"
86-
/>
64+
@open-table-index="tableDialog = true" />
8765
</v-navigation-drawer>
8866

89-
<v-navigation-drawer
90-
v-else
67+
<v-navigation-drawer v-else
9168
v-model="showRight"
9269
rail
93-
location="right"
94-
>
95-
<gm-tool-palette
96-
pc
70+
location="right">
71+
<gm-tool-palette pc
9772
:expanded="showRight"
9873
:selected="panel"
9974
:combatant="combatant"
10075
@select-panel="selectPanel"
10176
@open-dice-roller="diceDialog = true"
102-
@open-table-index="tableDialog = true"
103-
/>
77+
@open-table-index="tableDialog = true" />
10478
</v-navigation-drawer>
10579

106-
<v-footer
107-
app
80+
<v-footer app
10881
height="36"
109-
style="border-top: 1px solid rgba(255, 255, 255, 0.1)"
110-
>
111-
<v-row
112-
justify="space-between"
82+
style="border-top: 1px solid rgba(255, 255, 255, 0.1)">
83+
<v-row justify="space-between"
11384
align="center"
114-
no-gutters
115-
>
85+
no-gutters>
11686
<v-col>
11787
<pc-end-round :sheet="sheet" />
11888
</v-col>
@@ -124,37 +94,57 @@
12494
</v-layout>
12595
</div>
12696

127-
<v-dialog
128-
v-model="diceDialog"
97+
<v-dialog v-model="diceDialog"
12998
:fullscreen="mobile"
13099
max-height="80vh"
131-
max-width="80vw"
132-
>
133-
<gm-dice-roller
134-
:encounter="encounterInstance"
100+
max-width="80vw">
101+
<gm-dice-roller :encounter="encounterInstance"
135102
:selected="combatant"
136-
@close="diceDialog = false"
137-
/>
103+
@close="diceDialog = false" />
138104
</v-dialog>
139105

140-
<v-dialog
141-
v-model="tableDialog"
106+
<v-dialog v-model="tableDialog"
142107
:fullscreen="mobile"
143-
max-width="80vw"
144-
>
145-
<rollable-table-index
146-
:instance="encounterInstance"
108+
max-width="80vw">
109+
<rollable-table-index :instance="encounterInstance"
147110
:selected="combatant"
148-
@close="tableDialog = false"
149-
/>
111+
@close="tableDialog = false" />
150112
</v-dialog>
113+
114+
115+
<cc-solo-dialog v-model="leaveDialog"
116+
:close-on-click="false"
117+
title="Exit Active Mode?"
118+
:z-index="9999">
119+
<v-card flat
120+
tile>
121+
122+
<div class="text-center text-text ma-2">
123+
Do you want to save this encounter before exiting?</div>
124+
<v-divider class="my-3" />
125+
<v-card-actions class="pa-0">
126+
<cc-button variant="text"
127+
size="small"
128+
@click="handleLeave('cancel')">Cancel</cc-button>
129+
<v-spacer />
130+
<cc-button color="warning"
131+
size="small"
132+
variant="text"
133+
@click="handleLeave('exit')">Exit Without Saving</cc-button>
134+
<v-spacer />
135+
<cc-button color="accent"
136+
size="small"
137+
@click="handleLeave('save')">Save and Exit</cc-button>
138+
</v-card-actions>
139+
</v-card>
140+
</cc-solo-dialog>
151141
</div>
152142
</template>
153143

154144
<script setup lang="ts">
155145
import { ref, computed } from 'vue';
156146
import { useDisplay } from 'vuetify';
157-
import { useRoute } from 'vue-router';
147+
import { useRoute, onBeforeRouteLeave } from 'vue-router';
158148
import { PilotStore } from '@/stores';
159149
import ActorTelemetry from '../gm/EncounterPanels/_components/ActorTelemetry.vue';
160150
import ActorLogs from '../gm/EncounterPanels/_components/ActorLogs.vue';
@@ -190,6 +180,8 @@ const showRight = ref(false);
190180
const panel = ref('pc');
191181
const diceDialog = ref(false);
192182
const tableDialog = ref(false);
183+
const leaveDialog = ref(false);
184+
let resolveLeaveDialog: ((value: string) => void) | null = null;
193185
194186
const sheet = computed(() =>
195187
PilotStore().GetSheet(props.id || route.params.id as string || PilotStore().CurrentActiveID)
@@ -202,4 +194,28 @@ const encounterInstance = computed(() => sheet.value!.EncounterInstance);
202194
function selectPanel(p: string) {
203195
panel.value = panel.value === p ? 'pc' : p;
204196
}
197+
198+
function openLeaveDialog(): Promise<string> {
199+
leaveDialog.value = true;
200+
return new Promise((resolve) => {
201+
resolveLeaveDialog = resolve;
202+
});
203+
}
204+
205+
function handleLeave(choice: 'save' | 'exit' | 'cancel') {
206+
leaveDialog.value = false;
207+
resolveLeaveDialog?.(choice);
208+
resolveLeaveDialog = null;
209+
}
210+
211+
onBeforeRouteLeave(async () => {
212+
const choice = await openLeaveDialog();
213+
if (choice === 'save') {
214+
sheet.value?.Save();
215+
return true;
216+
} else if (choice === 'exit') {
217+
return true;
218+
}
219+
return false;
220+
});
205221
</script>

0 commit comments

Comments
 (0)