Logo Zephyrnet

Xây dựng ứng dụng tìm kiếm GIF trên máy tính để bàn gốc bằng NodeGui

Ngày:

NútGui là một thư viện mã nguồn mở để xây dựng các ứng dụng máy tính để bàn đa nền tảng với Node.js. Ứng dụng NodeGui có thể chạy trên macOS, Windows và Linux. Các ứng dụng được xây dựng bằng NodeGui được viết bằng JavaScript, được tạo kiểu bằng CSS và được hiển thị dưới dạng các tiện ích máy tính để bàn gốc bằng cách sử dụng Khung Qt.

Một số tính năng của NodeGui là:

  • widget gốc với hỗ trợ tích hợp cho chế độ tối
  • CPU và bộ nhớ thấp
  • tạo kiểu với CSS bao gồm hỗ trợ hoàn chỉnh cho bố cục Flexbox
  • hoàn thành hỗ trợ API Node.js và truy cập vào tất cả các mô-đun npm tương thích của Node.js
  • hỗ trợ gỡ lỗi tuyệt vời bằng cách sử dụng Công cụ dành cho nhà phát triển của Chrome
  • hỗ trợ TypeScript hạng nhất

NodeGui được cung cấp bởi khung Qt, giúp CPU và bộ nhớ hiệu quả hơn so với các giải pháp dựa trên Chromium khác như Electron. Điều này có nghĩa là các ứng dụng được viết bằng NodeGui không mở một phiên bản trình duyệt và hiển thị giao diện người dùng trong đó. Thay vào đó, tất cả các widget được hiển thị nguyên bản.

Hướng dẫn này sẽ trình bày cách cài đặt NodeGui và sử dụng nó để xây dựng trình tìm kiếm meme sống trong khay hệ thống và giao tiếp với API GIPHY.

Mã nguồn đầy đủ cho hướng dẫn này là có sẵn trên GitHub.

Cài đặt và thiết lập cơ bản

Đối với hướng dẫn này, giả định rằng bạn có Node.js v12 hoặc lớn hơn được cài đặt. Bạn có thể xác nhận rằng cả Node và npm đều khả dụng bằng cách chạy:

# This command should print the version of Node.js
node -v # This command should print the version of npm
npm -v

Nếu bạn cần trợ giúp với bước này, hãy xem hướng dẫn cài đặt Node.

NodeGui yêu cầu các công cụ biên dịch CMake và C ++ để xây dựng lớp C ++ gốc của dự án. Đảm bảo bạn cài đặt CMake> = 3.1 cùng với trình biên dịch C ++ hỗ trợ C ++ 11 trở lên. Các hướng dẫn chi tiết có một chút khác nhau tùy thuộc vào hệ điều hành của bạn.

macOS

Bạn nên cài đặt CMake bằng Homebrew. Chạy các lệnh sau trong một thiết bị đầu cuối sau khi cài đặt Homebrew:

brew install cmake
brew install make

Bạn có thể xác nhận cài đặt bằng cách chạy:

# This command should print the version of CMake which should be higher than 3.1
cmake --version make --version

Cuối cùng, bạn cần GCC / Clang để biên dịch mã C ++. Xác minh rằng bạn đã cài đặt GCC bằng lệnh này:

gcc --version

Nếu bạn chưa cài đặt GCC, hãy đảm bảo rằng bạn đã cài đặt Công cụ dòng lệnh cho Xcode or Công cụ dành cho nhà phát triển XCode từ Trang dành cho nhà phát triển của Apple.

Windows

Bạn có thể cài đặt CMake trên Windows bằng cách tải xuống bản phát hành mới nhất từ Trang tải xuống CMake.

Chúng tôi thực sự khuyên bạn nên sử dụng Powershell làm thiết bị đầu cuối ưu tiên trong Windows.

Bạn có thể xác nhận cài đặt CMake bằng cách chạy:

# This command should print the version of CMake which should be higher than 3.1
cmake --version

Cuối cùng, bạn cần một trình biên dịch C ++. Một khả năng sẽ là cài đặt Visual Studio 2017 trở lên. Bạn nên chọn Phát triển máy tính để bàn với C ++ khối lượng công việc trong quá trình cài đặt.

Linux

Chúng tôi sẽ tập trung vào Ubuntu 18.04 cho các mục đích của hướng dẫn này. Bạn nên cài đặt CMake bằng trình quản lý gói. Chạy các lệnh sau trong một thiết bị đầu cuối:

sudo apt-get install pkg-config build-essential
sudo apt-get install cmake make

Bạn có thể xác nhận cài đặt bằng cách chạy:

# This command should print the version of CMake which should be higher than 3.1
cmake --version make --version

Cuối cùng, bạn cần GCC để biên dịch mã C ++. Xác minh rằng bạn đã cài đặt GCC bằng lệnh:

# gcc version should be >= v7
gcc --version

Xin chào thế giới

Để bắt đầu với ứng dụng meme NodeGui của chúng tôi, chúng tôi sẽ sao chép dự án khởi đầu.

Lưu ý: Việc chạy này yêu cầu Git và npm.

Mở một thiết bị đầu cuối và chạy:

git clone https://github.com/nodegui/nodegui-starter memeapp
cd memeapp
npm install
npm start

Nếu mọi thứ suôn sẻ, bạn sẽ thấy ứng dụng NodeGui hello world đang hoạt động trên màn hình.

Xin chào thế giới ví dụ NodeGui

Theo mặc định, dự án nodegui-starter là một dự án TypeScript. Tuy nhiên, trong hướng dẫn này, chúng tôi sẽ viết ứng dụng của mình bằng JavaScript. Để chuyển đổi trình khởi động của chúng tôi thành một dự án JS, chúng tôi sẽ thực hiện các thay đổi nhỏ sau:

  1. Xóa index.ts tập tin trong src thư mục.

  2. Tạo một tệp mới index.js trong src thư mục với các nội dung sau:

    src / index.js

    const { QMainWindow, QLabel } = require('@nodegui/nodegui'); const win = new QMainWindow();
    win.setWindowTitle('Meme Search'); const label = new QLabel();
    label.setText('Hello World'); win.setCentralWidget(label);
    win.show(); global.win = win;
    
    

Về bản chất, ứng dụng NodeGui là một ứng dụng Node.js. Tất cả các API và tính năng được tìm thấy trong NodeGui đều có thể truy cập được thông qua @nodegui/nodegui mô-đun này có thể được yêu cầu giống như bất kỳ mô-đun Node.js nào khác. Ngoài ra, bạn có quyền truy cập vào tất cả các API Node.js và các mô-đun Node. NodeGui sử dụng các thành phần gốc thay vì các thành phần dựa trên web làm khối xây dựng.

Trong ví dụ trên, chúng tôi đã nhập QChínhCửa sổnhãn QL để tạo một cửa sổ gốc hiển thị dòng chữ “Hello World”.

Bây giờ hãy chạy lại ứng dụng:

npm start

Phiên bản JavaScript Hello World

Bây giờ chúng ta đã thiết lập cơ bản sẵn sàng, hãy bắt đầu xây dựng công cụ tìm kiếm meme của chúng ta 🥳.

Lưu ý: Nếu điều gì đó không hoạt động khi làm theo hướng dẫn này, hãy kiểm tra package.json để đảm bảo rằng dự án khởi động đã lấy được phiên bản NodeGui cập nhật nhất.

Hiển thị GIF động

Vì meme thường là GIF động, chúng ta sẽ bắt đầu bằng cách tạo một cửa sổ cơ bản hiển thị ảnh GIF từ một URL.

Để làm điều này, chúng tôi sẽ sử dụng QPhim cùng với QLabel. QMovie không phải là một widget mà là một vùng chứa có thể phát các hình ảnh động đơn giản. Chúng tôi sẽ sử dụng nó kết hợp với QLabel.

Ví dụ về cách sử dụng QMovie trông như thế này:

const movie = new QMovie();
movie.setFileName('/absolute/path/to/animated.gif');
movie.start(); const animatedLabel = new QLabel();
animatedLabel.setMovie(movie);

Vì chúng tôi muốn tải một hình ảnh từ một URL, chúng tôi không thể sử dụng QMovie'S setFileName phương thức này chỉ dành riêng cho các tệp cục bộ. Thay vào đó, chúng tôi sẽ tải xuống ảnh GIF bằng cách sử dụng axios làm bộ đệm và sử dụng phương pháp QMovie tảiTừ dữ liệu thay thế.

Vì vậy, hãy bắt đầu với cài đặt axios:

npm i axios

Bây giờ, hãy tạo một hàm sẽ lấy URL làm tham số và sẽ trả về một QMovie ví dụ cho GIF:

async function getMovie(url) { const { data } = await axios.get(url, { responseType: 'arraybuffer' }); const movie = new QMovie(); movie.loadFromData(data); movie.start(); return movie;
}

Sản phẩm getMovie hàm nhận một URL, yêu cầu axios tải xuống GIF làm bộ đệm và sau đó sử dụng bộ đệm đó để tạo QMovie ví dụ.

Bạn có thể nghĩ về QMovie như một lớp xử lý logic bên trong của việc phát từng khung hình ảnh động GIF. QMovie không phải là một widget, vì vậy nó không thể được hiển thị trên màn hình. Thay vào đó, chúng tôi sẽ sử dụng QLabel ví dụ và thiết lập QMovie với nó.

từ getMovie trả về một lời hứa, chúng ta cần thực hiện một số thay đổi đối với mã. Sau một số tái cấu trúc nhỏ, chúng tôi kết thúc với những điều sau.

src / index.js

const { QMainWindow, QMovie, QLabel } = require('@nodegui/nodegui');
const axios = require('axios').default; async function getMovie(url) { const { data } = await axios.get(url, { responseType: 'arraybuffer' }); const movie = new QMovie(); movie.loadFromData(data); movie.start(); return movie;
} const main = async () => { const win = new QMainWindow(); win.setWindowTitle('Meme Search'); const label = new QLabel(); const gifMovie = await getMovie( 'https://upload.wikimedia.org/wikipedia/commons/e/e3/Animhorse.gif' ); label.setMovie(gifMovie); win.setCentralWidget(label); win.show(); global.win = win;
}; main().catch(console.error);

Sản phẩm main chức năng là điểm vào của chúng tôi. Ở đây chúng tôi tạo một cửa sổ và một nhãn. Sau đó, chúng tôi tạo ra một QMovie ví dụ với sự giúp đỡ của chúng tôi getMovie và cuối cùng đặt QMovie đến một QLabel.

Chạy ứng dụng với npm start và bạn sẽ thấy một cái gì đó như thế này:

Ví dụ hoạt hình cơ bản cho thấy một con ngựa đang phi nước đại

Tìm nạp ảnh GIF từ API GIPHY

Giphy.com có ​​một API công khai mà bất kỳ ai cũng có thể sử dụng để tạo các ứng dụng tuyệt vời sử dụng ảnh GIF động. Để sử dụng GIPHY API, bạn nên đăng ký tại Develop.giphy.com và lấy khóa API. Bạn có thể tìm hướng dẫn thêm tại đây.

Chúng tôi sẽ sử dụng điểm cuối tìm kiếm tính năng để triển khai tìm kiếm meme của chúng tôi.

Hãy bắt đầu bằng cách viết một searchGifs chức năng sẽ có một searchTerms tham số làm đầu vào và yêu cầu GIF bằng cách sử dụng điểm cuối ở trên:

const GIPHY_API_KEY = 'Your API key here'; async function searchGifs(searchTerm) { const url = 'https://api.giphy.com/v1/gifs/search'; const res = await axios.get(url, { params: { api_key: GIPHY_API_KEY, limit: 25, q: searchTerm, lang: 'en', offset: 0, rating: 'pg-13' } }); return res.data.data;
}

Kết quả của hàm sau khi thực thi sẽ có dạng như sau:

[ { "type": "gif", "id": "dzaUX7CAG0Ihi", "url": "https://giphy.com/gifs/hello-hi-dzaUX7CAG0Ihi", "images": { "fixed_width_small": { "height": "54", "size": "53544", "url": "https://media3.giphy.com/media/dzaUX7CAG0Ihi/100w.gif?cid=725ec7e0c00032f700929ce9f09f3f5fe5356af8c874ab12&rid=100w.gif", "width": "100" }, "downsized_large": { "height": "220", "size": "807719", "url": "https://media3.giphy.com/media/dzaUX7CAG0Ihi/giphy.gif?cid=725ec7e0c00032f700929ce9f09f3f5fe5356af8c874ab12&rid=giphy.gif", "width": "410" }, ... }, "slug": "hello-hi-dzaUX7CAG0Ihi", ... "import_datetime": "2016-01-07 15:40:35", "trending_datetime": "1970-01-01 00:00:00" }, { type: "gif", ... }, ...
]

Kết quả về cơ bản là một mảng các đối tượng chứa thông tin về mỗi GIF. Chúng tôi đặc biệt quan tâm đến returnValue[i].images.fixed_width_small.url cho mỗi hình ảnh chứa URL tới GIF.

Hiển thị danh sách các GIF sử dụng phản hồi của API

Để hiển thị danh sách các GIF, chúng tôi sẽ tạo getGifViews chức năng sẽ:

  1. tạo một QWidget chứa
  2. tạo một QMovie tiện ích cho mỗi GIF
  3. tạo một QLabel từ mỗi QMovie ví dụ
  4. đính kèm mỗi QLabel như một đứa trẻ của QWidget chứa
  5. trả lại QWidget chứa

Mã trông như thế này:

async function getGifViews(listOfGifs) { const container = new QWidget(); container.setLayout(new FlexLayout()); const promises = listOfGifs.map(async gif => { const { url, width } = gif.images.fixed_width_small; const movie = await getMovie(url); const gifView = new QLabel(); gifView.setMovie(movie); gifView.setInlineStyle(`width: ${width}`); container.layout.addWidget(gifView); }); await Promise.all(promises); container.setInlineStyle(` flex-direction: 'row'; flex-wrap: 'wrap'; justify-content: 'space-around'; width: 330px; height: 300px; `); return container;
}

Hãy chia nhỏ điều này một chút.

Đầu tiên, chúng tôi tạo widget vùng chứa của chúng tôi. QWidgets về cơ bản là các widget trống hoạt động như các thùng chứa. Chúng tương tự như <div> các yếu tố trong thế giới web.

Tiếp theo, để gán các tiện ích con cho QWidget, chúng ta cần cung cấp cho nó một bố cục. A bố trí ra lệnh cho cách sắp xếp các widget con bên trong một trình cha mẹ. Ở đây chúng tôi chọn Bố cục linh hoạt.

Sau đó, chúng tôi sử dụng getMovie chức năng để tạo ra một QMovie ví dụ cho mỗi URL GIF. Chúng tôi chỉ định QMovie ví dụ cho một QLabel (tên gifView) và cung cấp cho nó một số kiểu cơ bản bằng cách sử dụng setInlineStyle phương pháp. Cuối cùng, chúng tôi thêm QLabel tiện ích con vào bố cục của vùng chứa bằng cách sử dụng layout.addWidget phương pháp.

Vì tất cả điều này đang diễn ra không đồng bộ, chúng tôi đợi mọi thứ giải quyết bằng cách sử dụng Promise.all, trước khi đặt một số kiểu vùng chứa và trả lại tiện ích vùng chứa.

Bây giờ chúng ta hãy sửa đổi main để xem danh sách các widget mà chúng tôi đã chuẩn bị.

src / index.js

const { FlexLayout, QLabel, QMainWindow, QMovie, QWidget } = require('@nodegui/nodegui');
const axios = require('axios').default;
const GIPHY_API_KEY = 'Your API key here'; async function getMovie(url) { ... }
async function searchGifs(searchTerm) { ... }
async function getGifViews(listOfGifs) { ... } const main = async () => { const win = new QMainWindow(); win.setWindowTitle('Meme Search'); const center = new QWidget(); center.setLayout(new FlexLayout()); // We get the list of gifs here const listOfGifs = await searchGifs('hello'); // We create the container with GIF view widgets const container = await getGifViews(listOfGifs); // We finally attach the container to the widget center.layout.addWidget(container); win.setCentralWidget(center); win.show(); global.win = win;
}; main().catch(console.error);

Nếu bạn chạy dự án sau khi thực hiện những thay đổi này, bạn sẽ thấy:

Danh sách các GIF "xin chào" được lấy từ API GIPHY

Tuyệt quá! Bây giờ, hãy thêm trường nhập tìm kiếm cùng với một nút để người dùng có thể tìm kiếm thứ gì đó khác ngoài ảnh GIF “xin chào”.

Thêm đầu vào và nút tìm kiếm

Hãy bắt đầu bằng cách tạo createSearchContainer hàm, sẽ chấp nhận một hàm gọi lại như một tham số. Điều này sẽ được gọi khi nút tìm kiếm được nhấp vào.

Đây là những gì hàm nên làm:

  1. tạo một QWidget vùng chứa mà chúng tôi sẽ thêm trường nhập tìm kiếm và nút khi còn nhỏ
  2. tạo một bố cục và gắn nó vào vùng chứa
  3. tạo đầu vào và nút tìm kiếm, sau đó đính kèm chúng vào FlexLayout
  4. đính kèm một trình xử lý sự kiện vào nút mà khi được nhấp vào, nút này sẽ gọi onSearch hàm gọi lại truyền cho nó bất kỳ văn bản nào có trong trường nhập văn bản
  5. trả lại QWidget chứa

Mã trông như thế này:

function createSearchContainer(onSearch) { const searchContainer = new QWidget(); searchContainer.setObjectName('searchContainer'); searchContainer.setLayout(new FlexLayout()); const searchInput = new QLineEdit(); searchInput.setObjectName('searchInput'); const searchButton = new QPushButton(); searchButton.setObjectName('searchButton'); searchButton.setText(' 🔎 '); searchButton.addEventListener('clicked', () => { onSearch(searchInput.text()); }); searchContainer.layout.addWidget(searchInput); searchContainer.layout.addWidget(searchButton); searchContainer.setStyleSheet(` #searchContainer { flex-direction: 'row'; padding: 10px; align-items: 'center'; } #searchInput { flex: 1; height: 40px; } #searchButton { margin-left: 5px; width: 50px; height: 35px; } `); return searchContainer;
}

Hy vọng rằng bạn có một ý tưởng hợp lý về những gì đang xảy ra ở đây, nhưng một điều mới cần lưu ý là phương thức setStyleSheet. Bạn có thể coi đây là một cách để áp dụng CSS cấp khối trong một lần. Nó rất giống với các bảng định kiểu chung trên Web, nhưng với sự khác biệt là trong NodeGui / Qt, một biểu định kiểu có thể được đính kèm vào bất kỳ khối nào chứ không chỉ trên toàn cục.

Để tạo kiểu cho một tiện ích con bằng biểu định kiểu, chúng ta cần thêm một objectName vào một tiện ích, mà chúng tôi sẽ sử dụng để tham chiếu nó trong biểu định kiểu. Điều này khá giống với một id trong thế giới web. Để thiết lập một objectName, chúng tôi sẽ sử dụng setObjectName phương pháp.

Bây giờ chúng ta hãy thêm cái này searchContainer đến cửa sổ chính.

src / index.js

const { FlexLayout, QLabel, QLineEdit, QMainWindow, QMovie, QPushButton, QWidget,
} = require('@nodegui/nodegui'); const axios = require('axios').default;
const GIPHY_API_KEY = 'Your API key here'; async function getMovie(url) { ... }
async function searchGifs(searchTerm) { ... }
async function getGifViews(listOfGifs) { ... }
function createSearchContainer(onSearch) { ... } const main = async () => { const win = new QMainWindow(); win.setWindowTitle('Meme Search'); const center = new QWidget(); center.setLayout(new FlexLayout()); // Here we create the search container const searchContainer = createSearchContainer(searchText => { console.log('searchText: ', searchText); }); // Here we add it to the center widget before we add the list of GIFs. center.layout.addWidget(searchContainer); const listOfGifs = await searchGifs('hello'); const container = await getGifViews(listOfGifs); center.layout.addWidget(container); win.setCentralWidget(center); win.show(); global.win = win;
}; main().catch(console.error);

Bây giờ, khi bạn khởi chạy ứng dụng và nhập nội dung nào đó vào trường tìm kiếm, bạn sẽ thấy bất kỳ thứ gì bạn đã tìm kiếm được ghi vào thiết bị đầu cuối của bạn.

Danh sách các GIF có đầu vào tìm kiếm

Kết nối Tìm kiếm với Chế độ xem GIF

Để tải GIF mới theo tìm kiếm của người dùng, chúng tôi cần thực hiện những việc sau:

  1. Bên trong lệnh gọi lại được kích hoạt khi nhấp vào nút tìm kiếm, hãy lấy văn bản tìm kiếm và sử dụng searchGifs chức năng nhận danh sách GIF mới.
  2. Tạo một vùng chứa mới cho những GIF này bằng cách sử dụng getGifViews chức năng.
  3. Xóa vùng chứa hiện có khỏi cửa sổ.
  4. Thêm vùng chứa mới vào cửa sổ.

Nếu chúng ta xáo trộn mọi thứ xung quanh một chút, chúng ta nhận được:

const main = async () => { const win = new QMainWindow(); win.setWindowTitle('Meme Search'); const center = new QWidget(); center.setLayout(new FlexLayout()); let container = new QWidget(); const searchContainer = createSearchContainer(async searchText => { try { // Create a new GIF container with new GIFs const listOfGifs = await searchGifs(searchText); const newGifContainer = await getGifViews(listOfGifs); // Remove existing container from the window center.layout.removeWidget(container); container.close(); // Add the new GIF container to the window center.layout.addWidget(newGifContainer); container = newGifContainer; } catch (err) { console.error('Something happened!', err); } }); center.layout.addWidget(searchContainer); win.setCentralWidget(center); win.show(); global.win = win;
};

Hãy chạy lại nó và xem điều kỳ diệu 🧙‍♂️.

Tiện ích tìm kiếm GIF được kết nối

Như bạn có thể thấy, khi bạn nhập nội dung nào đó vào hộp tìm kiếm và nhấn nút tìm kiếm, tiện ích của chúng tôi sẽ tìm nạp danh sách các GIF khớp với cụm từ tìm kiếm từ API GIPHY.

Trong khi tất cả điều này đang đi đúng hướng, bạn có thể nhận thấy rằng danh sách các ảnh GIF bị cắt ở dưới cùng và không có cách nào để cuộn chúng. Điều này là do chúng tôi đang sử dụng QWidget thùng chứa để hiển thị chúng. Để làm cho vùng chứa có thể cuộn được, chúng ta cần hoán đổi QWidget cho một Khu vực QScroll. Điều này cung cấp một chế độ xem cuộn vào một tiện ích con khác.

Chúng tôi sẽ bắt đầu bằng cách xóa height tài sản trong getGifViews chức năng:

async function getGifViews(listOfGifs) { ... container.setInlineStyle(` flex-direction: 'row'; flex-wrap: 'wrap'; justify-content: 'space-around'; width: 330px;
- height: 300px; `); return container;
}

Sau đó, chúng ta cần phải thay đổi src/index.js trông như thế này:

const { FlexLayout, QLabel, QLineEdit, QMainWindow, QMovie, QPushButton, QScrollArea, QWidget,
} = require('@nodegui/nodegui'); const axios = require('axios').default;
const GIPHY_API_KEY = 'Your API key here'; async function getMovie(url) { ... }
async function searchGifs(searchTerm) { ... }
async function getGifViews(listOfGifs) { ... }
function createSearchContainer(onSearch) { ... } const main = async () => { const win = new QMainWindow(); win.setWindowTitle('Meme Search'); const center = new QWidget(); center.setLayout(new FlexLayout()); const scrollArea = new QScrollArea(); scrollArea.setWidgetResizable(false); scrollArea.setInlineStyle('flex: 1; width: 350px; height: 400px;'); const searchContainer = createSearchContainer(async searchText => { try { const listOfGifs = await searchGifs(searchText); const newGifContainer = await getGifViews(listOfGifs); // Remove existing container from the scrollArea const oldContainer = scrollArea.takeWidget(); if (oldContainer) oldContainer.close(); // Add the new GIF container to the scrollArea scrollArea.setWidget(newGifContainer); } catch (err) { console.error('Something happened!', err); } }); center.layout.addWidget(searchContainer); center.layout.addWidget(scrollArea); win.setCentralWidget(center); win.show(); global.win = win;
}; main().catch(console.error);

Không có gì quá thú vị xảy ra ở đây. Chúng tôi đang tạo một cái mới QScrollArea, chúng tôi thêm vào bố cục bên dưới trường tìm kiếm. Chúng tôi cũng đang sử dụng QScrollArea'S phương thức takeWidget để xóa bất kỳ vùng chứa hiện có nào khỏi vùng cuộn, trước khi thêm các kết quả tìm kiếm mới.

Nếu bạn khởi chạy trình tìm kiếm meme, bây giờ bạn sẽ có các GIF có thể cuộn:

Tìm kiếm có thể cuộn

Thêm người nghe nhấp chuột để sao chép URL GIF để chia sẻ

Bây giờ chúng tôi có thể xem tất cả các GIF, chúng tôi muốn có thể chia sẻ chúng. Một cách nhanh chóng để thực hiện việc này là sao chép URL vào khay nhớ tạm thời chung bất cứ khi nào người dùng nhấp vào GIF mà họ chọn.

Sau đó, người dùng có thể chỉ cần điều hướng đến nơi họ muốn sử dụng GIF và chèn nó vào Ctrl/Cmd + V.

Để làm được điều đó, chúng ta phải:

  1. đính kèm trình nghe sự kiện thả chuột vào mỗi GIF
  2. bên trong lệnh gọi lại của trình nghe sự kiện, hãy sử dụng QClipboard lớp để sao chép URL vào khay nhớ tạm thời chung
  3. hiển thị một phương thức cho người dùng nói rằng URL đã được sao chép

Trình nghe sự kiện có thể được đính kèm bên trong getGifViews chức năng:

async function getGifViews(listOfGifs) { ... const promises = listOfGifs.map(async gif => { ... gifView.addEventListener(WidgetEventTypes.MouseButtonRelease, () => { const clipboard = QApplication.clipboard(); clipboard.setText(url, QClipboardMode.Clipboard); showModal( 'Copied to clipboard!', `You can press Cmd/Ctrl + V to paste the GIF url: ${url}` ); }); container.layout.addWidget(gifView); }); ... return container;
}

Ở đây, QApplication.clipboard trả về một đối tượng để tương tác với khay nhớ tạm. Chúng ta có thể sử dụng đối tượng này setText phương pháp để thay đổi nội dung thực tế của khay nhớ tạm.

Chúng tôi cũng đang sử dụng một showModal chức năng. Hãy xác định điều đó tiếp theo:

function showModal(title, details) { const modal = new QMessageBox(); modal.setText(title); modal.setDetailedText(details); const okButton = new QPushButton(); okButton.setText('OK'); modal.addButton(okButton, ButtonRole.AcceptRole); modal.exec();
}

Sản phẩm Tiện ích QMessageBox tương tự như hộp cảnh báo trong trình duyệt web. Nó có thể được sử dụng để tạm dừng tương tác của người dùng và hiển thị thông báo.

Cuối cùng, chúng ta cần nhập tất cả các tiện ích con mới này ở đầu src/index.js:

const { ButtonRole, FlexLayout, QApplication, QClipboardMode, QLabel, QLineEdit, QMainWindow, QMessageBox, QMovie, QPushButton, QScrollArea, QWidget, WidgetEventTypes,
} = require('@nodegui/nodegui');
const axios = require('axios').default;
const GIPHY_API_KEY = 'Your API key here'; async function searchGifs(searchTerm) { ... };
async function getGifViews(listOfGifs) { ... };
async function getMovie(url) { ... };
function createSearchContainer(onSearch) { ... };
function showModal(title, details) { ... }; const main = async () => { ... }; main().catch(console.error);

Nếu bạn khởi chạy trình tìm kiếm meme, bây giờ bạn sẽ có khả năng sao chép / dán URL GIF:

Sao chép URL GIF vào GIF khay nhớ tạm

Thêm biểu tượng khay hệ thống

Chúng tôi muốn ứng dụng của mình được ẩn trong khay hệ thống khi không sử dụng. Đối với điều này, chúng tôi sẽ tạo một biểu tượng khay hệ thống sẽ có một mục menu, khi nhấp vào, sẽ chuyển đổi chế độ hiển thị của tiện ích con đang chạy.

Các bước liên quan là:

  1. Tạo ra một QHệ ThốngKhayBiểu Tượng với một biểu tượng.
  2. Tạo menu cho biểu tượng khay hệ thống bằng QMenu. Đặt phiên bản menu làm menu ngữ cảnh của khay hệ thống.
  3. Tạo các mục menu bằng cách sử dụng Vật dụng QAction và thiết lập người nghe sự kiện để lắng nghe trigger sự kiện.
  4. Khi kích hoạt, ẩn hoặc hiển thị cửa sổ.

Hãy bắt đầu bằng cách yêu cầu các mô-đun cần thiết, sau đó thực hiện một thay đổi nhỏ đối với main chức năng để yêu cầu nó sử dụng biểu tượng của chúng tôi:

const { ButtonRole, FlexLayout, QApplication, QClipboardMode, QIcon, QLabel, QLineEdit, QMainWindow, QMenu, QMessageBox, QMovie, QAction, QPushButton, QScrollArea, QSystemTrayIcon, QWidget, WidgetEventTypes,
} = require('@nodegui/nodegui');
const axios = require('axios').default;
const path = require('path');
const iconImg = require('../assets/systray.png').default;
const GIPHY_API_KEY = 'Your API key here'; const main = async () => { ... win.show(); systemTrayIcon(win); global.win = win;
};

Như bạn có thể thấy, chúng tôi yêu cầu một biểu tượng từ assets thư mục. Nếu bạn đang theo dõi, bạn có thể tải xuống tệp biểu tượng từ đây.

Bây giờ đến chức năng tạo biểu tượng khay hệ thống:

function systemTrayIcon(win) { const icon = new QIcon(path.resolve(__dirname, iconImg)); const tray = new QSystemTrayIcon(); tray.setIcon(icon); tray.show(); // Menu that should pop up when clicking on systray icon. const menu = new QMenu(); tray.setContextMenu(menu); //Each item in the menu is called an action const visibleAction = new QAction(); menu.addAction(visibleAction); visibleAction.setText('Show/Hide'); visibleAction.addEventListener('triggered', () => { if (win.isVisible()) { win.hide(); } else { win.show(); } }); global.tray = tray;
}

Ở đây, chúng tôi đang tạo biểu tượng bằng cách sử dụng NodeGui's Lớp QIcon. Sau đó, chúng tôi đang sử dụng QSystemTrayIcon lớp để tạo biểu tượng khay hệ thống cho ứng dụng của chúng tôi.

Cuối cùng, chúng tôi cần điều chỉnh cài đặt webpack của mình (trong webpack.config.js) để ngăn webpack khỏi polyfilling __dirname:

const path = require('path'); module.exports = { ... node: {
- __dirname: true,
- __filename: true
+ __dirname: false,
+ __filename: false }, ...
}

Kết quả cuối cùng:

Tiện ích tìm kiếm cuối cùng

Một số tinh chỉnh cuối cùng

Xử lý lỗi

Trước khi chuyển sang đóng gói, chúng ta hãy sử dụng showModal chức năng và thêm hộp thoại xử lý lỗi:

const main = async () => { ... const searchContainer = createSearchContainer(async searchText => { try { ... } catch (err) { ... showModal('Something went wrong!', JSON.stringify(err)); } }); ...
};

Điều này sẽ cảnh báo cho người dùng, chẳng hạn, nếu có bất kỳ sự cố nào xảy ra với yêu cầu Ajax tìm nạp ảnh GIF từ GIPHY. Bạn có thể thử điều này bằng cách thay đổi khóa API của mình thành một thứ gì đó không hợp lệ, sau đó khởi chạy ứng dụng và cố gắng tìm kiếm ảnh GIF.

Cho phép người dùng nhập khóa API

Trong khi chúng tôi đang nói về chủ đề của khóa API, hãy thêm hộp thoại để cho phép người dùng nhập khóa API của họ. Điều này có nghĩa là nó không cần phải được mã hóa cứng trong chương trình:

const { ... QDialog, ...
} = require('@nodegui/nodegui');
...
let GIPHY_API_KEY = ''; async function searchGifs(searchTerm) { ... }
async function getGifViews(listOfGifs) { ... }
async function getMovie(url) { ... }
function createSearchContainer(onSearch) { ... }
function showModal(title, details) { ... }
function systemTrayIcon(win) { ... } function showAPIKeyDialog() { const dialog = new QDialog(); dialog.setLayout(new FlexLayout()); const label = new QLabel(); label.setText('Enter your Giphy API Key'); const input = new QLineEdit(); const okButton = new QPushButton(); okButton.setText('OK'); okButton.addEventListener('clicked', () => { GIPHY_API_KEY = input.text(); dialog.close(); }); dialog.layout.addWidget(label); dialog.layout.addWidget(input); dialog.layout.addWidget(okButton); dialog.setInlineStyle(` padding: 10; height: 150px; flex-direction: 'column'; align-items:'center'; justify-content: 'space-around'; `); dialog.exec();
} const main = async () => { ... showAPIKeyDialog(); global.win = win;
}; main().catch(console.error);

Như bạn có thể thấy, chúng tôi đang sử dụng QDialog phụ tùng để nhắc người dùng nhập liệu, sau đó lưu trữ bất cứ thứ gì họ cung cấp trong GIPHY_API_KEY Biến đổi. Nếu bạn đang muốn cải thiện kỹ năng NodeGui của mình sau khi đọc hướng dẫn này, bạn có thể xem xét việc cải thiện điều này - ví dụ: bằng cách duy trì khóa hệ thống tệp hoặc xác thực nó và cung cấp phản hồi cho người dùng.

Lưu ý: Đừng quên, mã nguồn hoàn chỉnh có sẵn tại đây: https://github.com/sitepoint-editors/memesearchapp-nodegui-tutorial.

Đóng gói ứng dụng để phân phối đa nền tảng

Sau khi tạo thành công ứng dụng, chúng tôi cần tạo các bản phân phối cho macOS, Windows và Linux để người dùng cuối có thể tải xuống và sử dụng.

Quá trình tạo các bản phân phối thường khác nhau đối với mỗi hệ điều hành, vì vậy để giảm bớt khó khăn, chúng tôi sẽ sử dụng công cụ đóng gói của NodeGui có tên là @nodegui/packer.

Sử dụng

Đầu tiên, hãy cài đặt trình đóng gói dưới dạng phụ thuộc nhà phát triển:

npm install --save-dev @nodegui/packer

Tiếp theo, sử dụng trình đóng gói để tạo mẫu triển khai:

npx nodegui-packer --init MemeApp

Về cơ bản, mẫu là một dự án dành riêng cho hệ điều hành có chứa mã để đóng gói thành công tất cả mã, nội dung và phụ thuộc của ứng dụng NodeGui. Lưu ý rằng bạn cần chạy điều này trong Windows, macOS và Linux riêng biệt để tạo ba mẫu khác nhau. Mẫu này cho phép bạn tinh chỉnh cài đặt triển khai cuối cùng cụ thể cho từng hệ điều hành. Bạn có thể điều chỉnh những thứ như thông tin công ty, biểu tượng và siêu dữ liệu khác để phù hợp với nhu cầu của mình.

Đối với Linux, mẫu trông như thế này:

.
└── deploy ├── config.json └── linux └── MemeApp ├── default.desktop ├── default.png └── qode.json

Lưu ý rằng bạn chỉ cần chạy lệnh init hàng loạt. Sau đó, bạn thực hiện các thay đổi đối với mẫu và cam kết nó trong repo của dự án.

Bước tiếp theo là thực sự xây dựng và đóng gói dự án thành một bản phân phối.

Xóa build nếu nó tồn tại:

rm -rf ./deploy/build

Sau đó, xây dựng ứng dụng bằng cách sử dụng webpack:

npm run build

Cuối cùng, chạy lệnh pack của trình đóng gói, chuyển nó dist thư mục như một đối số:

npx nodegui-packer --pack ./dist

Điều này sẽ dẫn đến những điều sau:

  • Trên macOS, trình đóng gói sẽ xuất một dmg tập tin.
  • Trên Linux, trình đóng gói sẽ xuất ra một AppImage, đó là một cái gì đó tương tự như một .app tệp trong macOS.
  • Trên Windows, trình đóng gói xuất một thư mục chứa tệp thực thi và tất cả các tệp tin.

Khi lệnh thành công, nó sẽ in thư mục đầu ra, thường nằm bên trong deploy/<os>/build danh mục. Hãy chắc chắn rằng bạn không cam kết thư mục này:

.
└── deploy ├── config.json └── linux ├── build │ └── MemeApp │ ├── Application-aed23d8-x86_64.AppImage │ ├── AppRun -> qode │ ├── default.desktop │ ├── default.png │ ├── dist │ │ ├── f59514675cec2e70ce8598286c94dc22.png │ │ ├── index.js │ │ └── nodegui_core-7b3e73f5fef149ae765d5ea5d13d5bb0.node │ ├── doc │ │ └── ... │ ├── lib │ │ └── ... │ ├── plugins │ │ └── ... │ ├── qode │ ├── qode.json │ └── qt.conf └── MemeApp ├── default.desktop ├── default.png └── qode.json

Bản phân phối Linux là deploy/linux/build/MemeApp/Application-aed23d8-x86_64.AppImage 🚀📦.

Kết luận

Trong hướng dẫn này, chúng tôi đã xây dựng thành công ứng dụng tìm kiếm meme trong thế giới thực bằng NodeGui với khoảng 200 dòng mã. Chúng tôi đã tìm hiểu một số khái niệm và khả năng cơ bản của thư viện. Chúng tôi cũng có thể đóng gói ứng dụng đã hoàn thiện thành một bản phân phối có thể được chia sẻ với người dùng cuối.

Tôi tin rằng NodeGui sẽ mở ra cánh cửa để tạo ra rất nhiều ứng dụng gốc thực sự hiệu quả với Node.js.

NodeGui cũng hỗ trợ các thư viện và khuôn khổ như React (chính thức), Angular (cộng đồng) và sớm Vue.js (cộng đồng). Vui lòng kiểm tra những thứ này và cho chúng một ngôi sao trên GitHub nếu chúng là thứ bạn quan tâm.

NodeGui là một thư viện mã nguồn mở sẽ được hưởng lợi rất nhiều từ những đóng góp mã. Nó có một cơ sở mã tương đối dễ hiểu và một cộng đồng rất hoan nghênh. Tôi khuyến khích mọi người giúp đỡ.

Cuối cùng, nhờ có nhiều widget có sẵn và tạo kiểu thông qua CSS, tôi tin rằng các ứng dụng NodeGui dễ phát triển như các ứng dụng web hoặc Electron. Tôi khuyến khích bạn xây dựng một cái gì đó thú vị của riêng bạn và chia sẻ nó với chúng tôi.

Hướng dẫn này là một đoạn trích từ Thư viện SitePoint Premium, nơi bạn có thể xây dựng bộ kỹ năng Node.js sẵn sàng cho công việc.

Nguồn: https://www.sitepoint.com/build-native-desktop-gif-searcher-app-using-nodegui/?utm_source=rss

tại chỗ_img

Tin tức mới nhất

tại chỗ_img

Trò chuyện trực tiếp với chúng tôi (chat)

Chào bạn! Làm thế nào để tôi giúp bạn?