Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
45972f4
feat: Initial add of AFC integration files
jimmyjon711 Nov 27, 2025
b840f20
feat: Adding AppNumberInput
jimmyjon711 Nov 27, 2025
0311d63
feat: Adding AFC Card to Dashboard
jimmyjon711 Nov 27, 2025
8ab95f4
feat: Adding AFC locales
jimmyjon711 Nov 27, 2025
92d7718
feat: Adding AFC to store
jimmyjon711 Nov 27, 2025
7d86acb
feat: Adding AFC icons to globals
jimmyjon711 Nov 27, 2025
d026d41
refactor: Updating spoolman to show which spools are loaded in each l…
jimmyjon711 Nov 27, 2025
1db00c0
refactor: Adding css to have pointer and width class for AFC integration
jimmyjon711 Nov 27, 2025
bffe18b
refactor: Adding ability to have smaller text and change color for Ma…
jimmyjon711 Nov 27, 2025
d8504d1
refactor: Adding ability to specify icon for AppDialog
jimmyjon711 Nov 27, 2025
047e6c8
refactor: Adding check to MMUCard so that it does not show up in Dash…
jimmyjon711 Nov 27, 2025
059bf06
refactor: Adding toolchange count to status tab, part of AFC integration
jimmyjon711 Nov 27, 2025
7d6ef87
chore: Fixing errors from linter
jimmyjon711 Nov 28, 2025
261266b
chore: Fixing rebase issue with locales file
jimmyjon711 Nov 28, 2025
b749192
Merge branch 'develop' into AFC_integration
pedrolamas Dec 1, 2025
548d21f
chore: optimize SVGs
pedrolamas Dec 2, 2025
1a862c1
refactor: move all mdi icons to globals.ts
pedrolamas Dec 2, 2025
73055e8
refactor: typing improvements
pedrolamas Dec 2, 2025
3e45f45
refactor: replace console with consola
pedrolamas Dec 2, 2025
dc823e2
Merge branch 'develop' into AFC_integration
pedrolamas Dec 2, 2025
61e7b5e
Merge branch 'develop' into AFC_integration
pedrolamas Dec 2, 2025
c59f4e9
Merge branch 'develop' into AFC_integration
pedrolamas Dec 2, 2025
fd4d093
refactor: remove icon from AppDialog
pedrolamas Dec 2, 2025
3bb6716
refactor: remove dead code
pedrolamas Dec 2, 2025
7aa3d2f
refactor: encode gcode string arguments
pedrolamas Dec 5, 2025
00288d8
Merge branch 'develop' into AFC_integration
pedrolamas Dec 5, 2025
b00a24d
fix: settings controls
pedrolamas Dec 5, 2025
d4a26c1
revert: MMU support already checked on Dashboard
pedrolamas Dec 5, 2025
9389830
Merge branch 'develop' into AFC_integration
pedrolamas Dec 5, 2025
227688d
refactor: typing improvements
pedrolamas Dec 5, 2025
a50a2c2
refactor: MacroBtn attributes inheritance
pedrolamas Dec 5, 2025
e34f64c
refactor: typing improvements
pedrolamas Dec 5, 2025
59a553a
Merge branch 'develop' into AFC_integration
pedrolamas Dec 6, 2025
dbf889e
refactor: typing improvements
pedrolamas Dec 6, 2025
5d7baf7
refactor: typing improvements
pedrolamas Dec 6, 2025
9c0cba6
refactor: typing and performance improvements
pedrolamas Dec 7, 2025
89c5ad3
fix: allow sorting Spools by Loaded Lane
pedrolamas Dec 7, 2025
5b19f83
refactor: minor tweaks
pedrolamas Dec 7, 2025
f8ce69f
fix: correct boolean check
pedrolamas Dec 7, 2025
91009ee
refactor: move all icons to globals.ts
pedrolamas Dec 7, 2025
4f9390c
refactor: simplify code
pedrolamas Dec 7, 2025
e0a9776
refactor: spool selection
pedrolamas Dec 7, 2025
58b3409
style: clean up classes and styles
pedrolamas Dec 7, 2025
fc38dd3
chore: remove test values
pedrolamas Dec 7, 2025
dc8589f
style: reverted width changes
pedrolamas Dec 7, 2025
bc591dc
fix: some issues from Copilot review
pedrolamas Dec 7, 2025
35291ed
fix: spool selection
pedrolamas Dec 7, 2025
68c8425
refactor: replace button type
pedrolamas Dec 7, 2025
b1ff288
style: settings menu
pedrolamas Dec 7, 2025
8e65f60
style: pretty print extruder name
pedrolamas Dec 7, 2025
f7f5974
refactor: typing improvements
pedrolamas Dec 7, 2025
20b6e91
refactor: simplify dialogs
pedrolamas Dec 7, 2025
83e8161
style: prettify some labels and titles
pedrolamas Dec 8, 2025
b4a3868
refactor: typing improvements
pedrolamas Dec 8, 2025
b0ac42d
Merge branch 'develop' into AFC_integration
pedrolamas Dec 8, 2025
6092820
refactor: typing improvements
pedrolamas Dec 8, 2025
b226e1b
fix: remove fullscreen property from AfcCard
pedrolamas Dec 8, 2025
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
61 changes: 61 additions & 0 deletions src/components/widgets/afc/AfcCard.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<template>
<collapsable-card
:title="$t('app.afc.Headline')"
icon="$afcIcon"
draggable
layout-path="dashboard.afc-card"
>
<template #menu>
<afc-card-buttons />
<afc-card-settings />
</template>
<v-card-text class="pt-1">
<afc-card-message />
<afc-card-bypass />
<afc-card-extruder
v-for="extruder in filteredExtruders"
:key="extruder"
:name="extruder"
class="mt-3"
/>
<afc-card-unit
v-for="unit in filteredUnits"
:key="unit"
:name="unit"
class="mt-3"
/>
</v-card-text>
</collapsable-card>
</template>
<script lang="ts">
import { Component, Mixins } from 'vue-property-decorator'
import AfcMixin from '@/mixins/afc'
import AfcCardMessage from '@/components/widgets/afc/AfcCardMessage.vue'
import AfcCardBypass from '@/components/widgets/afc/AfcCardBypass.vue'
import AfcCardExtruder from '@/components/widgets/afc/AfcCardExtruder.vue'
import AfcCardUnit from '@/components/widgets/afc/AfcCardUnit.vue'
import AfcCardButtons from '@/components/widgets/afc/AfcCardButtons.vue'
import AfcCardSettings from '@/components/widgets/afc/AfcCardSettings.vue'

@Component({
components: {
AfcCardMessage,
AfcCardBypass,
AfcCardExtruder,
AfcCardUnit,
AfcCardButtons,
AfcCardSettings
}
})
export default class AfcCard extends Mixins(AfcMixin) {
get filteredExtruders (): string[] {
return this.afcExtruders
.filter(extruder => !this.afcHiddenExtruders.includes(extruder))
}

get filteredUnits (): string[] {
return this.afcUnits
.filter(unit => !this.afcHiddenUnits.includes(unit))
}
}
</script>
268 changes: 268 additions & 0 deletions src/components/widgets/afc/AfcCardButtons.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,268 @@
<template>
<v-menu
:offset-y="true"
:close-on-content-click="false"
:title="$t('app.afc.Functions')"
left
>
<template #activator="{ on, attrs }">
<app-btn
icon
v-bind="attrs"
v-on="on"
>
<v-icon dense>
$menu
</v-icon>
</app-btn>
</template>
<v-list dense>
<v-list-item
v-for="command in commands"
:key="command.command"
>
<v-tooltip
top
:disabled="!command.description"
>
<template #activator="{ on, attrs }">
<app-btn
class="fill-width"
:disabled="!klippyReady || command.disabled"
small
v-bind="attrs"
v-on="on"
@click="sendGcode(command.command)"
>
<v-icon
v-if="command.icon"
small
left
>
{{ command.icon }}
</v-icon>
{{ command.text }}
</app-btn>
</template>
<span>
{{ command.description }}
</span>
</v-tooltip>
</v-list-item>
<v-list-item
v-for="macro in macros"
:key="macro.macroName"
>
<v-tooltip
top
:disabled="!macro.macro.description"
>
<template #activator="{ on, attrs }">
<macro-btn
v-bind="attrs"
:macro="macro.macro"
small
class="fill-width"
v-on="on"
@click="sendGcode($event)"
>
{{ macro.text }}
</macro-btn>
</template>
<span>
{{ macro.macro.description }}
</span>
</v-tooltip>
</v-list-item>
<v-list-item>
<app-btn
class="fill-width"
small
@click="showAfcSettings = true"
>
<v-icon
small
left
>
$afcSettings
</v-icon>
{{ $t('app.afc.AfcSettings') }}
</app-btn>
<afc-settings-dialog v-model="showAfcSettings" />
</v-list-item>
<v-list-item>
<app-btn
class="fill-width"
small
@click="downloadDebugJson"
>
<v-icon
small
left
>
$afcDebugJson
</v-icon>
{{ $t('app.afc.DebugJson') }}
</app-btn>
</v-list-item>
</v-list>
</v-menu>
</template>
<script lang="ts">
import { Component, Mixins } from 'vue-property-decorator'
import StateMixin from '@/mixins/state'
import AfcMixin from '@/mixins/afc'
import MacroBtn from '@/components/widgets/macros/MacroBtn.vue'
import AfcSettingsDialog from '@/components/widgets/afc/dialogs/AfcSettingsDialog.vue'
import type { GcodeCommands, KlipperPrinterAfcSettings, KlipperPrinterConfig, KlipperPrinterSettings, KlipperPrinterState } from '@/store/printer/types'
import downloadUrl from '@/util/download-url'
import type { Macro } from '@/store/macros/types'

type AfcCommand = {
icon: string,
text: string,
command: string,
description?: string,
disabled?: boolean
}

type AfcMacro = {
text: string,
macroName: string,
macro: Macro,
disabled?: boolean
}

@Component({
components: {
AfcSettingsDialog,
MacroBtn
}
})
export default class AfcCardButtons extends Mixins(StateMixin, AfcMixin) {
showAfcSettings = false

get printerSettings (): KlipperPrinterSettings {
return this.$typedGetters['printer/getPrinterSettings']
}

get printerConfig (): KlipperPrinterConfig {
return this.$typedGetters['printer/getPrinterConfig']
}

get availableCommands (): GcodeCommands {
return this.$typedGetters['printer/getAvailableCommands']
}

get commands () {
const availableCommands = this.availableCommands

const commands: AfcCommand[] = []

if ('AFC_CALIBRATION' in availableCommands) {
commands.push({
icon: '$afcCalibration',
text: this.$t('app.afc.Calibrate').toString(),
command: 'AFC_CALIBRATION',
description: availableCommands['AFC_CALIBRATION'].help,
disabled: this.printerPrinting
})
}

if (this.afc?.led_state === true) {
if ('TURN_OFF_AFC_LED' in availableCommands) {
commands.push({
icon: '$afcTurnOffLed',
text: this.$t('app.afc.LedOff').toString(),
command: 'TURN_OFF_AFC_LED',
description: availableCommands['TURN_OFF_AFC_LED'].help
})
}
} else {
if ('TURN_ON_AFC_LED' in availableCommands) {
commands.push({
icon: '$afcTurnOnLed',
text: this.$t('app.afc.LedOn').toString(),
command: 'TURN_ON_AFC_LED',
description: availableCommands['TURN_ON_AFC_LED'].help
})
}
}

if (
this.afc?.td1_present === true &&
'AFC_GET_TD_ONE_DATA' in availableCommands
) {
commands.push({
icon: '',
text: this.$t('app.afc.CaptureTd').toString(),
command: 'AFC_GET_TD_ONE_DATA',
description: availableCommands['AFC_GET_TD_ONE_DATA'].help,
disabled: this.printerPrinting
})
}

return commands
}

get macros () {
const settings: KlipperPrinterAfcSettings | undefined = this.printerSettings.afc

const afcMacros: AfcMacro[] = []

if (settings?.wipe) {
const macroName: string = settings.wipe_cmd || 'AFC_BRUSH'
const macro: Macro | undefined = this.$typedGetters['macros/getMacroByName'](macroName)

if (macro != null) {
afcMacros.push({
text: this.$t('app.afc.BrushNozzle').toString(),
macroName,
macro,
disabled: this.printerPrinting
})
}
}

if (settings?.park) {
const macroName: string = settings.park_cmd || 'AFC_PARK'
const macro: Macro | undefined = this.$typedGetters['macros/getMacroByName'](macroName)

if (macro != null) {
afcMacros.push({
text: this.$t('app.afc.ParkNozzle').toString(),
macroName,
macro,
disabled: this.printerPrinting
})
}
}

return afcMacros
}

downloadDebugJson () {
const printer: KlipperPrinterState = this.$typedState.printer.printer

const output = {
config: Object.fromEntries(
Object.entries(this.printerConfig)
.filter(([key]) => /^afc(?:$|_)/.test(key))
),
settings: Object.fromEntries(
Object.entries(this.printerSettings)
.filter(([key]) => /^afc(?:$|_)/.test(key))
),
printer: Object.fromEntries(
Object.entries(printer)
.filter(([key]) => /^afc(?:$|_)/.test(key))
),
}

const jsonString = JSON.stringify(output)
const url = `data:text/plain;charset=utf-8,${encodeURIComponent(jsonString)}`

downloadUrl('afc_debug.json', url)
}
}
</script>
23 changes: 23 additions & 0 deletions src/components/widgets/afc/AfcCardBypass.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<template>
<v-alert
v-if="bypassState"
type="warning"
class="mt-3"
dense
text
>
{{ $t('app.afc.BypassActive') }}
</v-alert>
</template>
<script lang="ts">
import { Component, Mixins } from 'vue-property-decorator'
import StateMixin from '@/mixins/state'
import AfcMixin from '@/mixins/afc'

@Component
export default class AfcCardBypass extends Mixins(StateMixin, AfcMixin) {
get bypassState (): boolean {
return this.afc?.bypass_state === true
}
}
</script>
Loading