Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion app/components/DevModeHud.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,21 @@
<template>
<div v-if="$config.public.DEV" class="dev-state" :class="hudPosition" @click="toggleHudPosition">
<div
v-if="$config.public.DEV"
class="dev-state"
:class="hudPosition"
@click="toggleHudPosition"
>
<div>
<CollapsibleContainer title="Sites">
<div>
<ul>
<li @click="goToSite('https://www.katiecooper.co/')">Classic</li>
<li @click="goToSite('https://nextjs.org/')">Marketing</li>
<li @click="goToSite('https://nextjs.org/docs')">Documentation</li>
<li @click="goToSite('https://rauno.me/craft')">Performance</li>
</ul>
</div>
</CollapsibleContainer>
<CollapsibleContainer title="userInteractionState">
<div v-for="[key, value] of Object.entries(userInteractionState)">
{{ key }}: {{ value }}
Expand All @@ -10,6 +25,7 @@
<div v-for="[key, value] of Object.entries(interactionsStore.$state)">
{{ key }}: {{ value }}
</div>
<div>currentContext: {{ interactionsStore.currentContext }}</div>
</CollapsibleContainer>
</div>
<div>
Expand All @@ -24,9 +40,11 @@ import useEventHandler from '@/components/Screens/useEventHandler'
import { useInteractionStore } from '~/store/interactions'
import DevListeners from '~/components/DevListeners.vue'
import CollapsibleContainer from '~/components/CollapsibleContainer.vue'
import { useHistoryStore } from '@/store/history'

const interactionsStore = useInteractionStore()
const { state: userInteractionState } = useEventHandler() // init event handling
const historyStore = useHistoryStore()

const hudPosition = ref<'left' | 'right' | 'closed'>('right')

Expand All @@ -47,6 +65,10 @@ function toggleHudPosition() {

console.log(hudPosition.value)
}

function goToSite(newUrl: string) {
historyStore.changeSiteData({ url: newUrl })
}
</script>

<style lang="scss" scoped>
Expand Down
26 changes: 7 additions & 19 deletions app/components/Screens/Artboard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -108,24 +108,11 @@ const selectedArtboards = useSelectedArtboardsStore()
const hoverArtboards = useHoverArtboardsStore()
const interactions = useInteractionStore()

watch(interactions.$state.internal, (internal) => {
// TODO: Pinia Getter is not working in Vue 2: isInteracting: computed(() => interactions.isInteracting),
let isOn = false

for (const key in internal) {
if (internal[key] === true) {
isOn = true
}
}

state.isInteracting = isOn
})

const state = reactive({
isLoading: false,
horizontalLayout: true,
panzoomEnabled: computed(() => interactions.panzoomEnabled),
isInteracting: false,
isInteracting: computed(() => interactions.isInteracting),
isHover: computed(() =>
computedVars.hoverArtboards.filter((item) => item === props.id).length
? true
Expand All @@ -145,18 +132,19 @@ const state = reactive({
*/
canInteractWithWebContext: computed(() => {
// This artboard must be 'selected'
if (!state.isSelected) return false
if (!state.isSelected) {
return false
}

// Artboard is selected, but user is also doing an interaction
// Disable interactions with the Web Context
if (state.isSelected && state.isInteracting) {
interactions.setWebInteractionState(false) // Update global state
return false
} else if (state.isSelected && !state.isInteracting)
} else if (state.isSelected && !state.isInteracting) {
// Artboard is selected and user is not interacting
// Allow interactions in WebPage!
interactions.setWebInteractionState(true) // Update global state
return true
return true
}
}),
})

Expand Down
63 changes: 52 additions & 11 deletions app/components/Screens/Artboards.vue
Original file line number Diff line number Diff line change
Expand Up @@ -76,15 +76,19 @@ onMounted(() => {
}
)

// Watch to see if the fullHeight changes, and then update the webview height
watch(data.artboards, async (newVal, oldVal) => {
// Watch to see if the fullHeight changes, and then update the webview height
// Set full-height artboards to full height if GUI setting is enabled
if (gui.isScreensFullHeight) {
for (const [index, artboard] of newVal.entries()) {
setArtboardToFullHeight(artboard.id)
console.info('set artboard to full height', artboard)
}
}
})

// Start tracking the user's context
initWebviewOrAppContextTracker()
})

// TODO Consider enabling this once panzoom is a Vue plugin?
Expand All @@ -102,6 +106,42 @@ onBeforeUnmount(() => {
stopViewportObserver()
})

function initWebviewOrAppContextTracker() {
// Check if the artboard is selected and user is interacting
const calculateInteractionMode = () => {
for (const artboard of data.artboards) {
const isSelected = data.selectedArtboards.includes(artboard.id)

if (isSelected && !data.isInteracting) {
interactions.setWebInteractionState(true)
return true
} else if (isSelected) {
interactions.setWebInteractionState(false)
return false
}
}
}

// Initial check
calculateInteractionMode()

watch(
() => data.selectedArtboards,
() => {
// Check if the artboard is selected and user is interacting
calculateInteractionMode()

// Check if empty
if (data.selectedArtboards.length >= 1) {
// Either the app or the web context
} else {
// Should definitely be the app context
interactions.setWebInteractionState(false)
}
}
)
}

function resize(artboard: Artboard) {
artboards.resizeArtboard(artboard)
}
Expand Down Expand Up @@ -180,24 +220,25 @@ function createSelectionInstance() {
return true
})
.on('start', (evt) => {
// TODO: This is always firing as Panzoom is enabled
if (data.panzoomEnabled) {
console.warn('Panzoom is enabled!')
disableSelections()
return false
// disableSelections()
// return false
}

// Always reset selected when dragging
selectedArtboards.empty()
if (userEventsState.canDragSelect === true) {
}

console.log('selection')
if (userEventsState.canDragSelect === true) {
console.log('selection')

// Update state
interactions.interactionSetState({
key: 'isSelectingArea',
value: true,
})
// Update state
interactions.interactionSetState({
key: 'isSelectingArea',
value: true,
})
}
})
.on(
'move',
Expand Down
37 changes: 17 additions & 20 deletions app/components/panzoom/Panzoom.vue
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ import useEventHandler from '../Screens/useEventHandler'
import { useDevStore } from '~/store/dev'
import { initialPanZoom } from './panzoomFns'


// Connect w/ Electron

const interactions = useInteractionStore()
Expand Down Expand Up @@ -229,8 +228,6 @@ function enableEventListeners() {
}
}



/**
* Handles wheel events (i.e. mousewheel)
* @param DOMElement DOM element that Panzoom is on
Expand Down Expand Up @@ -270,24 +267,24 @@ function wheelHandler(DOMElement, instance) {
* @param DOMElement DOM element that Panzoom is on
* @param instance The Panzoom instance
*/
function mouseHandlers(DOMElement, instance) {
// TODO These DO NOT WORK
function mouseHandlers(DOMElement: Element, instance) {
// TODO: These DO NOT WORK

// Emit start events
// const onEvents = ['mousedown', 'touchstart', 'gesturestart']
// onEvents.forEach((name) => {
// DOMElement.addEventListener(name, startEvents)
// })

// const offEvents = ['mouseup', 'touchend', 'gestureend']
// offEvents.forEach((name) => {
// DOMElement.removeEventListener(name, startEvents)
// DOMElement.addEventListener(name, endEvents)
// })

function startEvents(e) {
const onEvents = ['mousedown', 'touchstart', 'gesturestart']
const offEvents = ['mouseup', 'touchend', 'gestureend']

onEvents.forEach((name) => {
DOMElement.addEventListener(name, () => startEvents(name))
})
offEvents.forEach((name) => {
// DOMElement.removeEventListener(name, startEvents)
DOMElement.addEventListener(name, () => endEvents(name))
})

function startEvents(eventName: string) {
// Only continue if Panzoom is enabled
if (panzoomEnabled && userEventsState.canDragSelect === false) {
if (panzoomEnabled && !isInteracting) {
panzoomInstance.value?.setOptions({
cursor: 'grabbing',
})
Expand All @@ -302,7 +299,7 @@ function mouseHandlers(DOMElement, instance) {
}
}

function endEvents(e) {
function endEvents(eventName: string) {
panzoomInstance.value?.setOptions({
cursor: 'grab',
})
Expand All @@ -314,7 +311,7 @@ function mouseHandlers(DOMElement, instance) {
})

// TODO: Remove event listener for just this one event name
DOMElement.removeEventListener(name, endEvents)
DOMElement.removeEventListener(eventName, () => endEvents(eventName))
}
}

Expand Down
82 changes: 44 additions & 38 deletions app/store/interactions.ts
Original file line number Diff line number Diff line change
@@ -1,64 +1,70 @@
import { defineStore } from 'pinia'
import { watch } from 'vue'

interface State {
internal: {
isPanzooming: boolean
isResizingArtboard: boolean
isSelectingArea: boolean
}
isInteracting: boolean
isWebInteractionContext: boolean
panzoomEnabled: boolean
}

export const useInteractionStore = defineStore('interactions', {
state: (): State => ({
// isPanning: false,
// isZooming: false,
export const useInteractionStore = defineStore('interactions', () => {
const state = reactive<State>({
internal: {
isPanzooming: false,
isSelectingArea: false,
isResizingArtboard: false,
},
isInteracting: false,
isWebInteractionContext: false,
panzoomEnabled: true,
}),
getters: {
isInteracting(state) {
// Check if any of the internal properties are set to true
// If so, we say the user is interacting
let isOn = false
})

for (const s in state.internal) {
if (state[s] === true) {
isOn = true
}
}

return isOn
},
const getters = {
// TODO this should also take into consideration if 1+ screens are selected,
// or if there is a panzoom event happening
currentContext: computed(() =>
state.isWebInteractionContext ? 'web' : 'app'
),
}

/**
* Is the current user in the
* app context or the web interaction context?
*/
currentContext(state) {
// TODO this should also take into consideration if 1+ screens are selected,
// or if there is a panzoom event happening
return state.isWebInteractionContext ? 'web' : 'app'
},
},
actions: {
interactionSetState({ key, value }) {
if (this.internal[key] !== value) {
this.internal[key] = value
const actions = {
interactionSetState({
key,
value,
}: {
key: keyof State['internal']
value: boolean
}): void {
if (state.internal[key] !== value) {
state.internal[key] = value
}
},
setPanzoomState(value) {
this.panzoomEnabled = value
setPanzoomState(value: boolean): void {
state.panzoomEnabled = value
},
setWebInteractionState(value) {
this.isWebInteractionContext = value
setWebInteractionState(value: boolean): void {
state.isWebInteractionContext = value
},
},
}

// Dynamically set isInteracting if 1+ internal properties are true
watch(state.internal, () => {
// Check if any of the internal properties are set to true
// If so, we say the user is interacting
let isOn = false

for (const s in state.internal) {
if (state.internal[s as keyof (typeof state)['internal']] === true) {
isOn = true
}
}

state.isInteracting = isOn
})

return { ...toRefs(state), ...getters, ...actions, persist: true }
})