Skip to content

Commit

Permalink
feat: add print sizing
Browse files Browse the repository at this point in the history
  • Loading branch information
dni committed Jan 3, 2025
1 parent b1c5126 commit 5973ee7
Show file tree
Hide file tree
Showing 9 changed files with 153 additions and 107 deletions.
14 changes: 7 additions & 7 deletions crud.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ async def get_print(payment_hash: str) -> Optional[Print]:
)


async def delete_print(print_id: str) -> None:
await db.execute(
"DELETE FROM pay2print.print WHERE payment_hash = :id",
{"id": print_id},
)


async def create_printer(user_id: str, data: CreatePrinter) -> Printer:
printer = Printer(
user_id=user_id,
Expand Down Expand Up @@ -64,13 +71,6 @@ async def get_prints(printer_id: str) -> list[Print]:
)


async def delete_print(print_id: str) -> None:
await db.execute(
"DELETE FROM pay2print.print WHERE id = :id",
{"id": print_id},
)


async def get_printer(printer_id: str) -> Optional[Printer]:
return await db.fetchone(
"SELECT * FROM pay2print.printer WHERE id = :id",
Expand Down
2 changes: 1 addition & 1 deletion static/js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ window.app = Vue.createApp({
},
openFile(file_name) {
const print = this.prints.find(print => print.file === file_name)
return `/pay2print/api/v1/file/${print.id}`
return `/pay2print/api/v1/file/${print.payment_hash}`
},
getPrints(printer_id) {
LNbits.api
Expand Down
38 changes: 32 additions & 6 deletions static/js/public.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ window.app = Vue.createApp({
if (this.$refs.cameraStream) {
navigator.mediaDevices
.getUserMedia({
video: {FacingMode: {exact: 'environment'}},
video: {
FacingMode: 'user'
},
audio: false
})
.then(stream => {
Expand All @@ -32,15 +34,39 @@ window.app = Vue.createApp({
}
},
methods: {
mmToPx(mm) {
const dpi = 300
return Math.floor((mm * dpi) / 25.4)
},
takePicture() {
this.picture = true
this.webcam = false
this.$refs.cameraStream.style.display = 'none'
this.$refs.canvas.width = this.$refs.cameraStream.videoWidth
this.$refs.canvas.height = this.$refs.cameraStream.videoHeight
this.$refs.canvas
.getContext('2d')
.drawImage(this.$refs.cameraStream, 0, 0)
const targetWidth = this.mmToPx(width)
const targetHeight = this.mmToPx(height)
this.$refs.canvas.width = targetWidth
this.$refs.canvas.height = targetHeight
const originalWidth = this.$refs.cameraStream.videoWidth
const originalHeight = this.$refs.cameraStream.videoHeight
const hRatio = targetWidth / originalWidth
const vRatio = targetHeight / originalHeight
const ratio = Math.min(hRatio, vRatio)
const centerShift_x = (targetWidth - originalWidth * ratio) / 2
const centerShift_y = (targetHeight - originalHeight * ratio) / 2
const ctx = this.$refs.canvas.getContext('2d')
ctx.fillStyle = '#fff'
ctx.fillRect(0, 0, targetWidth, targetHeight)
ctx.drawImage(
this.$refs.cameraStream,
0,
0,
originalWidth,
originalHeight,
centerShift_x,
centerShift_y,
originalWidth * ratio,
originalHeight * ratio
)
},
uploadPicture() {
this.$refs.canvas.toBlob(blob => {
Expand Down
2 changes: 1 addition & 1 deletion tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,4 @@ async def on_invoice_paid(payment: Payment) -> None:
try:
await print_service(_print, printer)
except Exception as exc:
logger.error(f"Error printing {_print.id}: {exc}")
logger.error(f"Error printing {_print.payment_hash}: {exc}")
8 changes: 4 additions & 4 deletions templates/pay2print/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,14 @@
dense
v-model.trim="printerDialog.data.width"
type="text"
label="Width *"
label="Width (mm) *"
></q-input>
<q-input
filled
dense
v-model.trim="printerDialog.data.height"
type="text"
label="Height *"
label="Height (mm) *"
></q-input>
<div class="row q-mt-lg">
<q-btn
Expand Down Expand Up @@ -228,7 +228,7 @@ <h5 class="text-subtitle1 q-my-none">Prints</h5>
flat
dense
size="xs"
@click="openPrint(props.row.id)"
@click="openPrint(props.row.payment_hash)"
target="_blank"
icon="print"
color="primary"
Expand All @@ -241,7 +241,7 @@ <h5 class="text-subtitle1 q-my-none">Prints</h5>
flat
dense
size="xs"
@click="deletePrint(props.row.id)"
@click="deletePrint(props.row.payment_hash)"
icon="cancel"
color="pink"
>
Expand Down
179 changes: 92 additions & 87 deletions templates/pay2print/photo.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,101 +2,106 @@
{% endblock %} {% block footer %}{% endblock %} {% block page_container %}
<q-page-container>
<q-page>
<q-card class="q-mt-md">
<q-card-section v-if="invoice == null" class="q-mb-sm text-center">
<h2 class="text-h5">
Make a photo, upload and pay to print!
<p v-text="invoiceAmount"></p>
</h2>
<q-btn
v-if="webcam"
icon="camera"
@click="takePicture()"
size="1em"
color="primary"
class="q-mb-xs q-mt-sm cursor-pointer"
>Take picture</q-btn
>
<q-btn
v-if="picture"
icon="cloud_upload"
@click="uploadPicture()"
size="1em"
color="primary"
class="q-mb-xs q-mt-sm cursor-pointer"
>Upload and pay</q-btn
>
<q-btn
v-if="picture"
icon="cancel"
@click="reset"
size="1em"
color="secondary"
class="q-mb-xs q-mt-sm cursor-pointer"
>Cancel</q-btn
>
</q-card-section>
<video
id="video"
ref="cameraStream"
autoplay
style="display: none"
></video>
<h3 v-if="!webcam" class="text-h6 text-center">
Device does not support camera!
</h3>
<p class="text-center text-negative" v-text="webcamError"></p>
<canvas ref="canvas" width="0" height="0"></canvas>
<q-card-section
v-if="invoice != null && paid == false"
class="q-mb-sm text-center"
<div v-if="invoice == null" class="q-mb-sm text-center">
<h2 class="text-h5">
Make a photo, upload and pay to print!
<p v-text="invoiceAmount"></p>
</h2>
<q-btn
v-if="webcam"
icon="camera"
@click="takePicture()"
size="1em"
color="primary"
class="q-mb-xs q-mt-sm cursor-pointer"
>Take picture</q-btn
>
<h2 class="text-h6">Pay this invoice to print!</h2>
<lnbits-qrcode :value="invoice"></lnbits-qrcode>
<q-btn
icon="content_copy"
@click="copyText(invoice)"
size="1em"
color="primary"
class="q-mb-xs q-mt-sm cursor-pointer"
>Copy invoice</q-btn
>
<q-btn
icon="refresh"
@click="reset()"
size="1em"
color="secondary"
class="q-ml-md q-mb-xs q-mt-sm cursor-pointer"
>Reset
</q-btn>
</q-card-section>
<q-card-section
v-if="invoice != null && paid == true"
class="q-mb-sm text-center"
<q-btn
v-if="picture"
icon="cloud_upload"
@click="uploadPicture()"
size="1em"
color="primary"
class="q-mb-xs q-mt-sm cursor-pointer"
>Upload and pay</q-btn
>
<h2 class="text-h6">
<q-icon name="done" size="3em" color="green"></q-icon>
Invoice paid, document is printing!
</h2>
<div>
<q-icon name="print" size="3em" color="grey"></q-icon>
</div>
<q-btn
icon="refresh"
@click="reset()"
size="1em"
color="secondary"
class="q-mt-sm q-mb-xs cursor-pointer"
>Reset
</q-btn>
</q-card-section>
</q-card>
<q-btn
v-if="picture"
icon="cancel"
@click="reset"
size="1em"
color="secondary"
class="q-mb-xs q-mt-sm cursor-pointer"
>Cancel</q-btn
>
</div>
<video
id="video"
ref="cameraStream"
autoplay
style="
background: white;
display: none;
margin: auto;
width: 100%;
height: auto;
"
></video>
<h3 v-if="webcamError" class="text-h6 text-center">
Device does not support camera!
</h3>
<p class="text-center text-negative" v-text="webcamError"></p>
<canvas
ref="canvas"
width="0"
height="0"
style="margin: auto; width: 100%"
></canvas>
<div v-if="invoice != null && paid == false" class="q-mb-sm text-center">
<h2 class="text-h6">Pay this invoice to print!</h2>
<lnbits-qrcode :value="invoice"></lnbits-qrcode>
<q-btn
icon="content_copy"
@click="copyText(invoice)"
size="1em"
color="primary"
class="q-mb-xs q-mt-sm cursor-pointer"
>Copy invoice</q-btn
>
<q-btn
icon="refresh"
@click="reset()"
size="1em"
color="secondary"
class="q-ml-md q-mb-xs q-mt-sm cursor-pointer"
>Reset
</q-btn>
</div>
<div v-if="invoice != null && paid == true" class="q-mb-sm text-center">
<h2 class="text-h6">
<q-icon name="done" size="3em" color="green"></q-icon>
Invoice paid, document is printing!
</h2>
<div>
<q-icon name="print" size="3em" color="grey"></q-icon>
</div>
<q-btn
icon="refresh"
@click="reset()"
size="1em"
color="secondary"
class="q-mt-sm q-mb-xs cursor-pointer"
>Reset
</q-btn>
</div>
</q-page>
</q-page-container>
{% endblock %} {% block scripts %}
<script>
const amount = {{ amount }};
const printer_id = "{{ printer_id }}";
const width = {{ width }};
const height = {{ height }};
</script>
<script src="{{ static_url_for('pay2print/static', path='js/public.js') }}"></script>
{% endblock %}
2 changes: 1 addition & 1 deletion templates/pay2print/public.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ <h2 class="text-h5">
multiple="false"
field-name="file"
@uploaded="uploaded"
url="uploadUrl"
:url="uploadUrl"
></q-uploader>
</q-card-section>
<q-card-section
Expand Down
4 changes: 4 additions & 0 deletions views.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ async def public(printer_id: str, request: Request):
"printer_id": printer_id,
"amount": printer.amount,
"printer_name": printer.name,
"width": printer.width,
"height": printer.height,
},
)

Expand All @@ -53,5 +55,7 @@ async def photo(printer_id: str, request: Request):
"printer_id": printer_id,
"amount": printer.amount,
"printer_name": printer.name,
"width": printer.width,
"height": printer.height,
},
)
11 changes: 11 additions & 0 deletions views_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from .crud import (
create_print,
create_printer,
delete_print,
delete_printer,
get_print,
get_printer,
Expand Down Expand Up @@ -93,6 +94,16 @@ async def api_upload_print(printer_id: str, file: UploadFile) -> UploadPayment:
)


@pay2print_ext_api.delete(
"/print/{print_id}", dependencies=[Depends(require_admin_key)]
)
async def api_delete_print(print_id: str) -> None:
_print = await get_print(print_id)
if not _print:
raise HTTPException(HTTPStatus.NOT_FOUND, "Print not found.")
await delete_print(print_id)


@pay2print_ext_api.get("/file/{print_id}", dependencies=[Depends(check_user_exists)])
async def api_show_file(print_id: str) -> FileResponse:
_print = await get_print(print_id)
Expand Down

0 comments on commit 5973ee7

Please sign in to comment.