Before Chrome 80 (79.0.3945.130), you could get all downloaded items in Chrome by accessing to chrome://downloads/ and get downloaded items from global variable downloads.
var items = downloads.Manager.get().items_;
But it seems that since version 80, Google has hidden the Manager properties from the downloads variable, so I could not get downloaded items anymore.
I would appreciate it if you could tell me any idea about the new way to get downloaded items. (bow)
return document.querySelector('downloads-manager')
.shadowRoot.querySelector('#downloadsList')
.items.filter(e => e.state === 'COMPLETE')
.map(e => e.filePath || e.file_path || e.fileUrl || e.file_url);
Related
When the addon loads, the menu only display its Help-option.
Cloud Console logs: We're sorry, a server error occurred while reading from storage. Error code NOT_FOUND.
The addons works. I noticed some minor differences while testing though actual files (one for each file-type) and testing Script-editor>Run>Test as addon... Yet I've managed to get them both working. However once installed (direct or domain), the add-on will only show one alternativ: Help.
I follow the guidelines to the best of my ability and I've read up on the onInstall-issue but find myself at a loss.
Almost all code is shared in a common library: opAddonShared. Those file-agnostic functions are added to the end of the addon-menu: opAddonShared.addSharedMenu(ui, menu)
const langsClearEmptyCells = {en: "🧹 Clear Empty Cells", sv: "🧹 Ta bort tomma celler"};
const langsClearOtherSheets = {en: "🪒 Cut All Other Sheets", sv: "🪒 Skär bort andra blad"};
function onOpen(e) {
let ui = SpreadsheetApp.getUi();
let menu = ui.createAddonMenu();
if (e && e.authMode == ScriptApp.AuthMode.NONE) { // âš Addons are frustrating!
return menu.addItem('📥 Install', "onInstall").addToUi();
}
let isLimited = e && e.authMode == ScriptApp.AuthMode.LIMITED
let lang = isLimited ? Session.getActiveUserLocale() ? 'sv' : 'en' : opAddonShared.getLanguage()
menu.addItem(langsClearEmptyCells[lang] || langsClearEmptyCells['en'], 'removeEmpty')
menu.addItem(langsClearOtherSheets[lang] || langsClearOtherSheets['en'], 'deleteOtherSheets')
if(!isLimited) {
menu.addSeparator()
menu = opAddonShared.addSharedMenu(ui, menu) //Appends file-agnostic functions
}
menu.addToUi()
}
function onInstall(e){
opAddonShared.installSharedMenu()
onOpen(e);
}
let callAddonLibraryFunction = (functionString, args) => {return opAddonShared[functionString](args)};
The issue seem to have been versioning (file-menu matching GCP) and/or access-control for shared script (Drive-file or script-library).
After the "fix", the menu will contain the "📥 Install"; for each file. After running onInstall(), the menu will be fully listed. It must be installed per-file; not per-user as I had wished/expected.
The sidebars are not yet working properly.
I am following a tutorial to resize images via Cloud Functions on upload and am experiencing two major issues which I can't figure out:
1) If a PNG is uploaded, it generates the correctly sized thumbnails, but the preview of them won't load in Firestorage (Loading spinner shows indefinitely). It only shows the image after I click on "Generate new access token" (none of the generated thumbnails have an access token initially).
2) If a JPEG or any other format is uploaded, the MIME type shows as "application/octet-stream". I'm not sure how to extract the extension correctly to put into the filename of the newly generated thumbnails?
export const generateThumbs = functions.storage
.object()
.onFinalize(async object => {
const bucket = gcs.bucket(object.bucket);
const filePath = object.name;
const fileName = filePath.split('/').pop();
const bucketDir = dirname(filePath);
const workingDir = join(tmpdir(), 'thumbs');
const tmpFilePath = join(workingDir, 'source.png');
if (fileName.includes('thumb#') || !object.contentType.includes('image')) {
console.log('exiting function');
return false;
}
// 1. Ensure thumbnail dir exists
await fs.ensureDir(workingDir);
// 2. Download Source File
await bucket.file(filePath).download({
destination: tmpFilePath
});
// 3. Resize the images and define an array of upload promises
const sizes = [64, 128, 256];
const uploadPromises = sizes.map(async size => {
const thumbName = `thumb#${size}_${fileName}`;
const thumbPath = join(workingDir, thumbName);
// Resize source image
await sharp(tmpFilePath)
.resize(size, size)
.toFile(thumbPath);
// Upload to GCS
return bucket.upload(thumbPath, {
destination: join(bucketDir, thumbName)
});
});
// 4. Run the upload operations
await Promise.all(uploadPromises);
// 5. Cleanup remove the tmp/thumbs from the filesystem
return fs.remove(workingDir);
});
Would greatly appreciate any feedback!
I just had the same problem, for unknown reason Firebase's Resize Images on purposely remove the download token from the resized image
to disable deleting Download Access Tokens
goto https://console.cloud.google.com
select Cloud Functions from the left
select ext-storage-resize-images-generateResizedImage
Click EDIT
from Inline Editor goto file FUNCTIONS/LIB/INDEX.JS
Add // before this line (delete metadata.metadata.firebaseStorageDownloadTokens;)
Comment the same line from this file too FUNCTIONS/SRC/INDEX.TS
Press DEPLOY and wait until it finish
note: both original and resized will have the same Token.
I just started using the extension myself. I noticed that I can't access the image preview from the firebase console until I click on "create access token"
I guess that you have to create this token programatically before the image is available.
I hope it helps
November 2020
In connection to #Somebody answer, I can't seem to find ext-storage-resize-images-generateResizedImage in GCP Cloud Functions
The better way to do it, is to reuse the original file's firebaseStorageDownloadTokens
this is how I did mine
functions
.storage
.object()
.onFinalize((object) => {
// some image optimization code here
// get the original file access token
const downloadtoken = object.metadata?.firebaseStorageDownloadTokens;
return bucket.upload(tempLocalFile, {
destination: file,
metadata: {
metadata: {
optimized: true, // other custom flags
firebaseStorageDownloadTokens: downloadtoken, // access token
}
});
});
This may sound silly... but is there any way to embed all videos in a directory to a webpage? I'm hosting some videos on my website but right now you have to manually browse the directory and just click a link to a video.
I know I can just embed those videos to a html page but is there any way to make it adapt automatically when I add new videos?
How you do this will depend on how you are building your server code and web page code, but the example below which is node and angular based does exactly what you are asking:
// GET: route to return list of upload videos
router.get('/video_list', function(req, res) {
//Log the request details
console.log(req.body);
// Get the path for the uploaded_video directory
var _p;
_p = path.resolve(__dirname, 'public', 'uploaded_videos');
//Find all the files in the diectory and add to a JSON list to return
var resp = [];
fs.readdir(_p, function(err, list) {
//Check if the list is undefined or empty first and if so just return
if ( typeof list == 'undefined' || !list ) {
return;
}
for (var i = list.length - 1; i >= 0; i--) {
// For each file in the directory add an id and filename to the response
resp.push(
{"index": i,
"file_name": list[i]}
);
}
// Set the response to be sent
res.json(resp);
});
});
This code is old in web years (i.e. about 3 years old) so the way node handles routes etc is likely different now but the concepts remains the same, regardless of language:
go to the video directory
get the lit of video files in it
build them into a JSON response and send them to the browser
browser extracts and displays the list
The browser code corresponding to the above server code in this case is:
$scope.videoList = [];
// Get the video list from the Colab Server
GetUploadedVideosFactory.getVideoList().then(function(data) {
// Note: should really do some type checking etc here on the returned value
console.dir(data.data);
$scope.videoList = data.data;
});
You may find some way to automatically generate a web page index from a directory, but the type of approach above will likely give you more control - you can exclude certain file names types etc quite easily, for example.
The full source is available here: https://github.com/mickod/ColabServer
Is there a way to get/set the USB Hardware ID's for Mic/Camera in Chromium browser from the command line.
I could not able to find out. The requirement is to set a particular Camera/Mic during runtime without manually updating in chrome://settings/content in the chromium browser.
It will be great if I can get some link or some sample code. Thanks !!!
You can use the --use-fake-ui-for-media-stream CLI flag to suppress the permissions dialog from showing up when you have a media stream. It will allow by default.
In terms of selecting a particular microphone or camera with a CLI flag, I don't believe it's possible. However, you can access and select the device to be used in JavaScript.
The navigator.mediaDevices.enumerateDevices object returns the following information:
The device kind - audioinput or videoinput
The device label - e.g. Built-in Microphone, Logitech bla, FaceTime HD Camera, etc.
The device Id - e.g. bd9759740e6c29df7703d0bfg62vbbc726fcb9422fdb948a35550835a840b328
The device group Id - If 2+ devices share the same physical device, they can have group Id
The Id is generated per session, so it's not something we can hardcode, but the label is unlikely to change. This means you could traverse the list and get the device Id that matches the string. I did this with async/await but you can use Promises or transpile to ES5 if need be:
(async() => {
const getFaceTimeCamId = async() => {
try {
const devices = await navigator.mediaDevices.enumerateDevices();
const faceTimeCam = devices.find(device =>
device.kind === 'videoinput' && device.label === 'FaceTime HD Camera');
return (faceTimeCam && faceTimeCam.deviceId) || undefined;
} catch(err) {
console.log(`${err.name}: ${err.message}`);
}
}
console.log(await getFaceTimeCamId());
})();
You can then set the constraints object for your stream to include the deviceId you want, for example, when using MediaDevices.getUserMedia.
const constraints = {
video: { deviceId: { exact: faceTimeCamId } }
};
I've not fully tested this as I don't have another camera or mic at hand, but hopefully this is of some help. I don't know your exact use case so probably made some assumptions.
I'm trying to run the "Using IndexedDB" sample code on https://developer.mozilla.org/en-US/docs/IndexedDB/Using_IndexedDB
Right out of the gate I stumble with the first line of code:
window.indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB;
Using Firebug I see that window.indexedDB is undefined as expected for FF 15, window.webkitIndexedDB is undefined as expected (FF isn't webkit) but window.mozIndexedDB is null but not undefined. If it's null that tells me it exists but doesn't have a valid value/isn't initialized.
This is with Firefox 15.0.1 on OSX 10.6.8 and Ubuntu 12.04. Can somebody tell me why I'm not able to see/use window.mozIndexedDB? Am I doing something wrong?
For completeness, here's my JavaScript file:
window.indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB;
var request = window.indexedDB.open("MyTestDatabase", 3);
var db;
request.onerror = function (event) {
alert("Oops, request.onerror");
};
request.onsuccess = function (event) {
// Do something with request.result!
alert("Made it to request.onsuccess");
db = request.result;
};
// This event is only implemented in recent browsers
request.onupgradeneeded = function (event) {
alert("Made it to request.onupgradeneeded");
};
db.onerror = function (event) {
alert("Database error (db.onerror): " + event.target.errorCode);
};
My original HTML5 application uses jQuery Mobile & REST WS. In development I would run it directly from the file system and it works fine. For sharing with coworkers I have it running behind Apache httpd.
While adding the IndexedDB, I was trying to test by viewing files from the file system via the browser. It didn't work and that's what caused me to go back to square one and try running the example code from Mozilla.
It appears IndexedDB requires a domain even if it's localhost. I simply placed my code under public_html and viewed it via httpd/localhost and it's working perfectly.