cjquines / qboard Goto Github PK
View Code? Open in Web Editor NEWThe efficient digital whiteboard.
Home Page: https://cjquines.com/qboard/
License: MIT License
The efficient digital whiteboard.
Home Page: https://cjquines.com/qboard/
License: MIT License
Exports to old version and cannot process new version files
Change to "show left side?"
I like the exported PDF to be qboard date time.pdf or something that won't give me file(n).pdf.
Paste an image (clipboard, or upload from input in latest commit) and do undo-redo. After some number of iterations (usually first), image will not appear. Continue to do it; eventually it will reappear.
Issue is at least as old as 816493c and occurs on CJ's demo too.
(@cjquines please put the commit hash as a comment in the hosted html file)
reproduce: make two objects, select both, scale both, undo, redo
see qboard.ts objectModified, which tries to save e.target.toJSON and partially revert it. undoing then redoing is not the same; indicates that maybe something is wrong with oldObject?
alternatively, maybe should try to use transform matrix, see https://stackoverflow.com/questions/38999034/how-does-transforming-points-with-a-transformmatrix-work-in-fabricjs/53710375#53710375
See: pihart#5
Reproduce: Import https://pihart.github.io/qboard/demos/123.json (included as text below), navigate to second page, export.
[{"version":"3.6.3","objects":[{"type":"path","version":"3.6.3","originX":"left","originY":"top","left":465.88,"top":164.87,"width":231.32,"height":402.2,"fill":null,"stroke":"#000000","strokeWidth":4,"strokeDashArray":[0,0],"strokeLineCap":"round","strokeDashOffset":0,"strokeLineJoin":"round","strokeMiterLimit":10,"scaleX":1,"scaleY":1,"angle":0,"flipX":false,"flipY":false,"opacity":1,"shadow":null,"visible":true,"clipTo":null,"backgroundColor":"","fillRule":"nonzero","paintFirst":"fill","globalCompositeOperation":"source-over","transformMatrix":null,"skewX":0,"skewY":0,"id":1,"strokeUniform":false,"path":[["M",467.87554714340115,313.20681599006025],["Q",467.87954714340117,313.20281599006023,468.35257106478196,312.25693751285155],["Q",468.8255949861627,311.3110590356428,472.3733285306363,308.00051142710925],["Q",475.9210620751099,304.6899638185756,495.078837651032,287.19126611360787],["Q",514.2366132269541,269.6925684086401,529.8466191689907,256.6867889601311],["Q",545.4566251110274,243.68100951162205,554.2077300589251,236.35050092636553],["Q",562.9588350068227,229.019992341109,580.6975027291907,215.06832539482554],["Q",598.4361704515586,201.11665844854204,614.9922603257687,190.0026269338848],["Q",631.5483501999788,178.8885954192276,643.6106225975418,173.44980770612582],["Q",655.6728949951048,168.01101999302404,659.6936524609591,167.30161564540032],["Q",663.7144099268136,166.59221129777663,670.5733830997763,168.48395923162843],["Q",677.432356272739,170.3757071654802,683.5817394295127,178.41566520118892],["Q",689.7311225862866,186.45562323689762,692.3328082879987,202.7719502939402],["Q",694.9344939897106,219.08827735098276,695.4075179110914,239.18811831686037],["Q",695.8805418324722,259.287959282738,695.170987905695,271.3478782951696],["Q",694.461433978918,283.4077973076013,692.3328082879985,309.41934718405366],["Q",690.2041825970791,335.4308970605061,688.3120508221441,360.0236292211453],["Q",686.4199190472092,384.61636138178454,685.9468951258284,406.844424411099],["Q",685.4738712044477,429.07248744041345,685.9468951258284,440.1865279756364],["Q",686.4199190472092,451.3005685108593,687.602496895367,470.69103219081023],["Q",688.7850747435249,490.08149587076116,690.4406765130636,505.2154613004443],["Q",692.0962782826023,520.3494267301274,693.5153861361564,531.2270201974624],["Q",694.9344939897106,542.1046136647973,695.6440479164876,546.1245385592574],["Q",696.3536018432646,550.1444634537177,697.2996496860262,555.8197162758388],["Q",698.2456975287878,561.4949690979599,698.7187214501686,564.3326045295862],["Q",699.1917453715494,567.1702399612125,699.1917453715494,568.1161003972898],["L",699.1917453715494,569.0659608333672]]},{"type":"path","version":"3.6.3","originX":"left","originY":"top","left":520.27,"top":526.92,"width":365.19,"height":26.9,"fill":null,"stroke":"#000000","strokeWidth":4,"strokeDashArray":[0,0],"strokeLineCap":"round","strokeDashOffset":0,"strokeLineJoin":"round","strokeMiterLimit":10,"scaleX":1,"scaleY":1,"angle":0,"flipX":false,"flipY":false,"opacity":1,"shadow":null,"visible":true,"clipTo":null,"backgroundColor":"","fillRule":"nonzero","paintFirst":"fill","globalCompositeOperation":"source-over","transformMatrix":null,"skewX":0,"skewY":0,"id":2,"strokeUniform":false,"path":[["M",522.2741281586627,555.8237343169703],["Q",522.2781281586628,555.8197343169703,523.697236012217,555.5832692079509],["Q",525.1163438657711,555.3468040989316,530.5561730957678,554.4009256217228],["Q",535.9960023257645,553.455047144514,546.8757329645816,550.8538948630385],["Q",557.7554636033987,548.252742581563,583.7721762628717,543.9963345369521],["Q",609.7888889223447,539.7399264923412,623.5067991788582,538.0846166058116],["Q",637.2247094353717,536.4293067192821,668.9177813302376,534.5375858471273],["Q",700.6108532251036,532.6458649749726,729.9388055130657,531.4635213887445],["Q",759.2667578010279,530.2811778025164,784.3373865283273,530.0446766112343],["Q",809.4080152556268,529.8081754199521,819.3416619622706,529.5717103109328],["Q",829.2753086689142,529.3352452019135,844.8853507003628,529.0987620517628],["Q",860.4953927318113,528.8622789016121,873.9767729829285,529.0987620517628],["L",887.4621532340458,529.3392452019135]]}],"background":"white"},{"version":"3.6.3","objects":[{"type":"path","version":"3.6.3","originX":"left","originY":"top","left":420.94,"top":245.15,"width":475.93,"height":339.07,"fill":null,"stroke":"#000000","strokeWidth":4,"strokeDashArray":[0,0],"strokeLineCap":"round","strokeDashOffset":0,"strokeLineJoin":"round","strokeMiterLimit":10,"scaleX":1,"scaleY":1,"angle":0,"flipX":false,"flipY":false,"opacity":1,"shadow":null,"visible":true,"clipTo":null,"backgroundColor":"","fillRule":"nonzero","paintFirst":"fill","globalCompositeOperation":"source-over","transformMatrix":null,"skewX":0,"skewY":0,"id":3,"strokeUniform":false,"path":[["M",422.9375889134024,290.03289252466845],["Q",422.9415889134024,290.02889252466844,424.1241667615603,289.319479156479],["Q",425.3067446097181,288.6100657882896,439.4976787876125,283.17128709575354],["Q",453.6886129655068,277.7325084032174,478.5227477768219,270.6384468858489],["Q",503.35688258813707,263.54438536848033,517.0747928446506,260.4703118895318],["Q",530.7927031011641,257.39623841058324,581.4070205665557,252.1939067859351],["Q",632.0213380319475,246.991575161287,645.5027182830648,247.22804929087204],["Q",658.9840985341822,247.46452342045708,668.9177813302376,247.70100657060777],["Q",678.8514641262932,247.9374897207585,688.5485808275405,250.53862396110264],["Q",698.2456975287878,253.1397582014468,700.8473832304999,257.3962023283205],["Q",703.449068932212,261.6526464551942,700.3743593091192,277.4960432941981],["Q",697.2996496860263,293.339440133202,673.4115627174729,330.4650305448773],["Q",649.5234757489193,367.5906209565526,637.4612033513561,383.19755268653716],["Q",625.398930953793,398.8044844165217,603.4029757601744,431.4371746128696],["Q",581.4070205665558,464.06986480921756,566.7430624672808,491.26380337472654],["Q",552.0791043680057,518.4577419402355,546.4027090432007,535.7199294333554],["Q",540.7263137183959,552.9821169264754,541.435867645173,561.7314883303735],["Q",542.1454215719501,570.4808597342716,544.7471072736622,574.0278904929559],["Q",547.3487929753743,577.5749212516401,561.3031971478722,582.3042955965525],["Q",575.2576013203702,587.0336699414648,604.3490236029361,584.6689827690086],["Q",633.4404458855018,582.3042955965525,670.5733830997763,574.7372677788825],["Q",707.7063203140508,567.1702399612125,725.9180119577995,563.1502609433581],["Q",744.1297036015482,559.1302819255038,776.0593055018104,552.2726855171545],["Q",807.9889074020726,545.4150891088053,833.2961022241805,540.685714763893],["Q",858.6032970462882,535.9563404189806,872.0846772974054,535.0104799829032],["Q",885.5660575485226,534.0646195468258,888.8772610875999,534.5375858471273],["Q",892.1884646266772,535.0105521474287,895.7361981711508,536.4293247604135],["Q",899.2839317156245,537.8480973733981,898.3378838728629,540.2127845458542],["L",897.3878360301012,542.5814717183105]]}],"background":"white"},{"version":"3.6.3","objects":[{"type":"path","version":"3.6.3","originX":"left","originY":"top","left":542.51,"top":175.88,"width":385,"height":702.38,"fill":null,"stroke":"#000000","strokeWidth":4,"strokeDashArray":[0,0],"strokeLineCap":"round","strokeDashOffset":0,"strokeLineJoin":"round","strokeMiterLimit":10,"scaleX":1,"scaleY":1,"angle":0,"flipX":false,"flipY":false,"opacity":1,"shadow":null,"visible":true,"clipTo":null,"backgroundColor":"","fillRule":"nonzero","paintFirst":"fill","globalCompositeOperation":"source-over","transformMatrix":null,"skewX":0,"skewY":0,"id":4,"strokeUniform":false,"path":[["M",614.9882603257686,210.10649496145948],["Q",614.9922603257686,210.10249496145948,616.411332089911,208.9201513752314],["Q",617.8304038540532,207.7378077890033,648.8139579115539,195.67788877657165],["Q",679.7975119690547,183.61796976414,693.5154222255683,181.48976574183453],["Q",707.2333324820819,179.36156171952905,732.7769851307622,178.4156742217546],["Q",758.3206377794426,177.46978672398018,781.9721947425998,181.01681748266446],["Q",805.623751705757,184.56384824134872,825.964105129837,190.71203128150853],["Q",846.3044585539169,196.86021432166834,854.3459734856256,200.17077997133327],["Q",862.3874884173342,203.4813456209982,871.1385933652319,210.10246789976242],["Q",879.8896983131297,216.7235901785266,883.2009018522069,223.81765169589517],["Q",886.5121053912842,230.91171321326374,884.3834797003648,243.4445534231684],["Q",882.2548540094454,255.97739363307306,877.2880126114176,266.6184859091259],["Q",872.3211712133899,277.2595781851788,849.3791681770097,303.0346719731775],["Q",826.4371651406295,328.8097657611762,791.9058775386553,358.60482052589794],["Q",757.3745899366811,388.3998752906196,733.4865390575394,412.51967723322014],["Q",709.5984881783976,436.6394791758207,703.449068932212,444.20648895235934],["Q",697.2996496860263,451.77349872889795,691.3867604452371,461.7051776367614],["Q",685.4738712044477,471.6368565446248,686.6564490526056,475.18388730330906],["Q",687.8390269007634,478.73091806199335,699.9013353877384,482.0415197939211],["Q",711.9636438747134,485.3521215258488,724.7354701990535,486.06149881177544],["Q",737.5072965233936,486.77087609770206,772.5116080467487,487.48027142476013],["Q",807.5159195701038,488.1896667518182,837.7899197008275,491.7366975105025],["Q",868.0639198315511,495.2837282691867,889.8233450197733,503.32370434602683],["Q",911.5827702079956,511.36368042286693,916.7861055220078,515.3836053173271],["Q",921.98944083602,519.4035302117873,926.4832222232551,531.2269660740683],["Q",930.9770036104902,543.0504019363492,922.9354886787816,564.805534747625],["Q",914.8939737470729,586.5606675589006,890.0598389357579,616.119257214603],["Q",865.2257041244427,645.6778468703053,847.723566407471,661.9941739273479],["Q",830.2214286904995,678.3105009843906,783.8643626069465,712.5984649850053],["Q",737.5072965233936,746.88642898562,680.9800898172125,785.6673202632592],["Q",624.4528831110315,824.4482115408982,584.4817301896487,852.3515273923338],["L",544.5065772682658,880.2588432437694]]}],"background":"white"}]
src/lib/action.ts
Should not overwrite existing document.
Either it should
I've accidentally navigated away from the page, losing all my content, more times than I'd like to admit. This is completely human error, but could be sorted in software. When I click the back button on my mouse I got back to the new tab page, it's right where my thumb sits, so accidental taps are common. If I use my pen this isn't a problem but sometimes I switch to a GUI of something to show rather than whiteboard.
I've seen sites that are active have a pop up "are you sure" box. Simple yes or not to allow or stop.
Cannot type the digits 0
and 1
because of the help modal event listener. Solution: proceed with default behavior when target is <input>
.
For each page x in pdf, add the content of x as a new page.
Use images if easier, but later change it to get the actual vectors from the pdf.
Can hang if you're scrubbing through pages
Edit: actually depending on how fabric works this might not be possible
Pasting large or high-res images can completely cover the screen, even on large high-res monitors. Images should be capped by percentage of total screen space, by each dimension independently. Maybe cap at 80% height and 80% width.
reproduce: make object, undo, redo, try to select it
Desktop verison where I can keep old qboards and keep my keybindings. A systems similar to Onenote would be nice.
JSON.stringify(this.pagesJson) === JSON.stringify(pages)
this is pretty much the only place we're expecting errors, so errors here should be explicitly handled.
Can replace with the file's history stacks if we add that to the file format
Currently they only change the global style for future drawings. Also, when an object is selected, the context menu shouldn't even touch the global styles (at least when the context menu was triggered by clicking on the selected object)
title
Exports a single blank page. Reproduce: draw an object and try to save
when switching to none until the page is reloaded
reproduce: make object, rotate it, move it, undo. it undoes all transforms
to see that it shouldn't undo all transforms, do undo undo and redo redo redo
Add text boxes (w/ bold, italics, subscript, superscript, highlighting, etc. -- most I probably won't use, but it's a good thing to add regardless) and latex rendering.
Edit: this is very obviously an enhancement, not something super important (except to me, latex is life).
Paste external image (clipboard), select all twice
Paste external images in from clipboard. I often talk about systems talking to other systems, for example. "git talking to github". This request is to be able to paste images, such as the GitHub logo, so that I can draw connectivity/activity/etc between components.
Support for image types that have transparency, such as PNG, would allow them to fit nicely into the board.
Ability to move and scale the images would allow them to fit into the rest of the content.
Page numbers k and k+1 both got rendered as what should've been page k + 1's content. When exported as JSON, obj.pages[k - 1] and obj.pages[k] are identical, so the content was lost. Same when exporting as PDF, so I think internally pagesJSON was incorrectly modified due to a race condition. (Page number k was a very large page in terms of bezier curves so maybe that's why.)
Not sure how to reproduce.
Hey, I've been using your demo for a short while, but since last week it's not been working. I then tried to build this into a Linux container that I could run locally and remove dependence from your demo. However, I have not built a node/react app before. I am comfortable with containers/docker, Linux, etc. The Docker config I do create I will share back to this project.
Would you be willing to share the deploy steps to stand this up, and I will work on packaging that into a Linux container.
Doesn't make sense to keep appending to previous issue #6
I thought this was already an issue.
At least check whether the document is modified or whether it contains no objects before confirming.
@cjquines can we also do the iterative check again?
Module parse failed: Cannot use keyword 'await' outside an async function (67:20)
src/lib/clipboard.ts 67:20
File was processed with these loaders:
* ./node_modules/@pmmmwh/react-refresh-webpack-plugin/src/loader/index.js
* ./node_modules/awesome-typescript-loader/dist/entry.js
You may need an additional loader to handle the result of these loaders.
| if (obj._objects) {
| obj.canvas = this.canvas;
> await obj.forEachObject((object) => {
| this.canvas.getNextId().then((id) => {
| object.id = id;
Issue is due to clipboard.ts
and the ctrl one if it exists
Mobile UI enhancement
This can be a press and hold menu. Alternatively, accept image files from the input.
The background of the .active button is the same as the background of the :hover other buttons
After fixing #23
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.