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
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.
Can replace with the file's history stacks if we add that to the file format
Exports a single blank page. Reproduce: draw an object and try to save
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
See: pihart#5
After fixing #23
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
This can be a press and hold menu. Alternatively, accept image files from the input.
Can hang if you're scrubbing through pages
Edit: actually depending on how fabric works this might not be possible
Doesn't make sense to keep appending to previous issue #6
Mobile UI enhancement
I thought this was already an issue.
Cannot type the digits 0
and 1
because of the help modal event listener. Solution: proceed with default behavior when target is <input>
.
src/lib/action.ts
Paste external image (clipboard), select all twice
Exports to old version and cannot process new version files
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
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.
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)
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.
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
JSON.stringify(this.pagesJson) === JSON.stringify(pages)
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"}]
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.
this is pretty much the only place we're expecting errors, so errors here should be explicitly handled.
Should not overwrite existing document.
Either it should
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)
I like the exported PDF to be qboard date time.pdf or something that won't give me file(n).pdf.
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.
Desktop verison where I can keep old qboards and keep my keybindings. A systems similar to Onenote would be nice.
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?
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).
The background of the .active button is the same as the background of the :hover other buttons
Change to "show left side?"
title
and the ctrl one if it exists
when switching to none until the page is reloaded
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.