Skip to content

Commit 332c8e8

Browse files
committed
add --copy option
1 parent 7b1c34c commit 332c8e8

File tree

6 files changed

+131
-58
lines changed

6 files changed

+131
-58
lines changed

index.js

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ const { normalize } = require("path")
88
const { recordVideo } = require("./src/recordVideo")
99
const { takeScreenshot } = require("./src/takeScreenshot")
1010
const open = require("open")
11+
const { bgRed, bold } = require("kleur")
12+
const { selectOption } = require("./src/selectOption")
13+
const logUpdate = require("log-update")
1114

1215
const version = require(join(__dirname, "./package.json")).version
1316

@@ -33,20 +36,42 @@ const imageTypes = {
3336
png: true,
3437
}
3538

39+
/**
40+
* @param {any} message
41+
*/
42+
function fail(message) {
43+
console.error(bgRed(" ERROR "), message)
44+
console.error("\nRun with", bold("--help"), "for usage information.")
45+
process.exit(1)
46+
}
47+
3648
async function run() {
3749
try {
3850
const [type = "", filename, ...others] = cli.input
3951

40-
const mode =
52+
/**
53+
* @type {"video" | "image" | null}
54+
*/
55+
let mode =
4156
type in imageTypes ? "image" : type in videoTypes ? "video" : null
4257

4358
if (!mode) {
44-
cli.showHelp(1)
59+
const idx = await selectOption("What do you want to capture?", [
60+
"Video",
61+
"Screenshot",
62+
])
63+
mode = idx === 0 ? "video" : "image"
64+
logUpdate(
65+
`💡 Hint! In the future you can run ${bold(
66+
`npx android-capture ${mode}`,
67+
)}\n`,
68+
)
69+
logUpdate.done()
70+
await new Promise((r) => setTimeout(r, 1000))
4571
}
4672

4773
if (others.length) {
48-
console.error("Unexpected arguements: ", others.join(" "))
49-
cli.showHelp(1)
74+
fail("Unexpected arguements: " + others.join(" "))
5075
}
5176

5277
const extension = mode === "image" ? "png" : "mp4"
@@ -58,12 +83,18 @@ async function run() {
5883
generateFilename(defaultFilename, extension),
5984
)
6085

86+
if (cli.flags.copy && mode === "video") {
87+
fail(`The ${bold("--copy")} option does not work with video.`)
88+
}
89+
90+
const useTemporaryFile = !filename && cli.flags.copy && !cli.flags.open
91+
6192
await init()
6293

6394
if (mode === "video") {
6495
await recordVideo(outPath)
6596
} else {
66-
await takeScreenshot(outPath)
97+
await takeScreenshot(outPath, useTemporaryFile)
6798
}
6899

69100
if (cli.flags.open) {

src/cli.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const { bold } = require("kleur")
1+
const { bold, grey } = require("kleur")
22
const meow = require("meow")
33

44
module.exports.cli = meow(
@@ -10,6 +10,9 @@ module.exports.cli = meow(
1010
1111
Options
1212
13+
${bold("--copy")} ${grey("(image capture only)")}
14+
Copies the screenshot to the clipboard. Currently macOS only.
15+
1316
${bold("--full-res")}
1417
Record video in full resolution (may not work in emulators).
1518
Images are always full-resolution.
@@ -50,6 +53,10 @@ module.exports.cli = meow(
5053
type: "boolean",
5154
default: true,
5255
},
56+
copy: {
57+
type: "boolean",
58+
default: false,
59+
},
5360
},
5461
allowUnknownFlags: false,
5562
},

src/copy-image-macos

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#!/usr/bin/osascript
2+
3+
on run args
4+
set thePath to (first item of args)
5+
set the clipboard to (read thePath as «class PNGf»)
6+
end

src/getDevice.js

Lines changed: 2 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
const { bgRed, bold, bgBlue, cyan, gray } = require("kleur")
2-
const logUpdate = require("log-update")
3-
const { pushKeyboardContext, popKeyboardContext } = require("./keyboardInput")
1+
const { bgRed, bold } = require("kleur")
2+
const { selectOption } = require("./selectOption")
43

54
const { spawnSafeSync } = require("./spawnSafeSync")
65

@@ -53,48 +52,3 @@ function parseDeviceLine(line) {
5352
const isUSB = properties.some((p) => p.startsWith("usb:"))
5453
return { id, model, isUSB }
5554
}
56-
57-
/**
58-
* @param {string} title
59-
* @param {string[]} options
60-
* @returns {Promise<number>}
61-
*/
62-
async function selectOption(title, options) {
63-
return new Promise((resolve) => {
64-
let selection = 0
65-
const draw = () => {
66-
const lines = [" " + bgBlue(` ${title} `), ""]
67-
for (let i = 0; i < options.length; i++) {
68-
lines.push(
69-
" " +
70-
(i === selection
71-
? cyan().bold("• [" + (i + 1) + "]")
72-
: gray(" [" + (i + 1) + "]")) +
73-
" " +
74-
options[i],
75-
)
76-
}
77-
lines.push("", "Use up/down arrow keys and hit [ENTER]")
78-
logUpdate(lines.join("\n"))
79-
}
80-
81-
draw()
82-
pushKeyboardContext({
83-
handleKeyPress(key) {
84-
if (key === "\r") {
85-
// enter!
86-
popKeyboardContext()
87-
resolve(selection)
88-
} else if (key === "\u001b[B") {
89-
// arrow down!
90-
selection = Math.min(selection + 1, options.length - 1)
91-
draw()
92-
} else if (key === "\u001b[A") {
93-
// arrow up!
94-
selection = Math.max(selection - 1, 0)
95-
draw()
96-
}
97-
},
98-
})
99-
})
100-
}

src/selectOption.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
const { cyan, gray, bold } = require("kleur")
2+
const logUpdate = require("log-update")
3+
const { pushKeyboardContext, popKeyboardContext } = require("./keyboardInput")
4+
5+
/**
6+
* @param {string} title
7+
* @param {string[]} options
8+
* @returns {Promise<number>}
9+
*/
10+
module.exports.selectOption = async function selectOption(title, options) {
11+
return new Promise((resolve) => {
12+
let selection = 0
13+
const draw = () => {
14+
const lines = [" " + bold(` ${title} `), ""]
15+
for (let i = 0; i < options.length; i++) {
16+
lines.push(
17+
" " +
18+
(i === selection
19+
? cyan().bold("• [" + (i + 1) + "]")
20+
: gray(" [" + (i + 1) + "]")) +
21+
" " +
22+
options[i],
23+
)
24+
}
25+
lines.push("", "Use up/down arrow keys and hit [ENTER]")
26+
logUpdate(lines.join("\n"))
27+
}
28+
29+
draw()
30+
pushKeyboardContext({
31+
handleKeyPress(key) {
32+
if (key === "\r") {
33+
// enter!
34+
popKeyboardContext()
35+
resolve(selection)
36+
} else if (key === "\u001b[B") {
37+
// arrow down!
38+
selection = Math.min(selection + 1, options.length - 1)
39+
draw()
40+
} else if (key === "\u001b[A") {
41+
// arrow up!
42+
selection = Math.max(selection - 1, 0)
43+
draw()
44+
}
45+
},
46+
})
47+
})
48+
}

src/takeScreenshot.js

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,41 @@
1-
const { bold } = require("kleur")
1+
const { bold, bgRed } = require("kleur")
22
const { adb } = require("./adb")
3+
const { cli } = require("./cli")
4+
const { tmpdir, platform } = require("os")
5+
const { join, basename } = require("path")
6+
const { unlinkSync } = require("fs")
7+
const { spawnSafeSync } = require("./spawnSafeSync")
38

49
/**
510
* @param {string} outFile
11+
* @param {boolean} useTemporaryFile
612
*/
7-
module.exports.takeScreenshot = async (outFile) => {
13+
module.exports.takeScreenshot = async (outFile, useTemporaryFile) => {
814
const internalFilePath = "/sdcard/android-capture-image.png"
15+
const externalFilePath = useTemporaryFile
16+
? join(tmpdir(), basename(outFile))
17+
: outFile
918
console.log("Taking screenshot...\n")
1019
adb("shell", "screencap", "-p", internalFilePath)
11-
adb("pull", internalFilePath, outFile)
20+
adb("pull", internalFilePath, externalFilePath)
1221
adb("shell", "rm", internalFilePath)
13-
console.log("Image saved to", bold(outFile))
22+
if (cli.flags.copy) {
23+
if (platform() === "darwin") {
24+
spawnSafeSync(join(__dirname, "copy-image-macos"), [externalFilePath])
25+
console.log("Image copied to clipboard!\n")
26+
} else {
27+
console.error(
28+
bgRed(" ERROR "),
29+
"--copy option currently only works on macOS.",
30+
)
31+
console.error(
32+
"Contribute support for other platforms at\n\n https://github.com/ds300/android-capture\n",
33+
)
34+
}
35+
}
36+
if (useTemporaryFile) {
37+
unlinkSync(externalFilePath)
38+
} else {
39+
console.log("Image saved to", bold(outFile))
40+
}
1441
}

0 commit comments

Comments
 (0)