Xem phim với sub trên bất kì trang web nào. Bạn đã thử chưa?

Hiện tại mình đang muốn xem phim mà có EngSub những nói thật là hơi khó tìm được nguồn.
Và một người bạn trên công ty đã chỉ cho mình một cách rất hay mà mình muốn share cho các bạn.
Đó là vẫn xem phim trên các trang web như phimmoi.net (cái này mình đã thử) hoặc các trang khác và add thêm English sub vào.
Đầu tiên là bạn đang dùng trình duyệt Chrome và thêm extension Substital Link tại đây
Sau đó trang phim bạn cần ví dụ nhu phimmoi.com và mình muốn show English sub cho phim Zootopia Link phim
Các bạn cứ bật phim lên nhé tiện test luôn.
Sau đó tìm Engsub cho phim này thường sẽ có trên Subscene. Ví dụ đây là link mình tìm được Link sub
Bạn vào trang kia rồi tải English Sub về rồi giải nén ra.
Tiếp theo Click vào extension rồi click vào tên phim

Nó sẽ show lên như thế này:

Các bạn chỉ cần kéo file Sub có định dạng SRT vào là được

Bingo Sub giờ đã hiện ra ngay dưới rồi nhé.

Cài đặt SSH keys cho nhiều tải khoản Bitbucket/Github

Như bài trước mình có hướng dẫn các bạn cách tạo SSH Key: Cách tạo SSH
Nhưng có một vấn đề là bạn không chỉ sử dụng 1 account github mà có thể là account nội bộ của công ty hay account bitbucket, account gitlab.
Rất nhiều tài khoản và không thể chung 1 SSH key được:
Vậy khi muốn dùng SSH Key cho nhiều tài khoản khác nhau thì bạn cần config cho chúng:
Bước 1: Tạo SSH cho 1 tài khoản khác.

$ ssh-keygen -t rsa -C "your_email@youremail.com"

Bước 2: Tạo tên file. Thường mình sẽ để là id_rsa_name_company (hoặc gì đó tương tự tên host cũng được)

– Các bước tiếp theo thì bạn có thể xem lại bài viết tạo SSH key của mình
Bước 3: Sau khi tạo xong SSH giờ là config SSH đó theo host. Chúng ta chỉ cần chỉnh sửa file Config là được nó nằm ngay trong thư mục SSH Key.

cd .ssh
open .


Bước 4: Mở file config bằng Editor sau đó chỉ cần thay đổi lại content là được:

– Nó sẽ có 3 phần:
+ Host: là tên host có thể là server công ty hoặc đơn giản là github.com hoặc bitbucket.com
+ HostName: tương tự host
+ IndentityFile: là đường dẫn đến file public key mà bạn muốn link

Tách logic và UI trong React Native. Bạn đã thử chưa?

Thường khi code với 1 màn hình ngoài giao diện trong phần Render thì sẽ có rất nhiều các logic khác ví dụ get data từ server các bạn sẽ để lẫn lộn trong đó. Việc đó là rất khó tránh khỏi. Hôm nay mình sẽ nói về việc vì sao nên tách logic và UI ra.
Đầu tiên mình sẽ có 1 file để demo. Các bạn hay để ý đoạn code sau:



import React, { Component } from 'react';
import {
  Platform,
  StyleSheet,
  Text,
  View,
  ScrollView,
  TextInput,
  TouchableOpacity,
  Alert,
  FlatList
} from 'react-native';
import firebase from 'react-native-firebase';
import Todo from './src/component/Todo';

export default class ListTask extends Component {
  constructor(props) {
    super(props);
    this.ref = firebase.firestore().collection('todos');
    this.unsubcribe = null;
    super();
    this.state = {
      textInput: '',
      loading: true,
      todos: [],
    }
  }

  componentDidMount() {
    this.unsubcribe = this.ref.onSnapshot(this.onCollectionUpdate)
  }

  onCollectionUpdate = (querySnapshot) => {
    const todos = [];
    querySnapshot.forEach((doc) => {
      const { title, complete } = doc.data();
      todos.push({
        key: doc.id,
        doc,
        title,
        complete,
      })

      this.setState({
        todos,
        loading: false
      });
    });
  }

  componentWillUnmount() {
    this.unsubcribe();
  }

  updateTextInput(value) {
    this.setState({ textInput: value });
  }

  addTodo() {
    this.ref.add({
      title: this.state.textInput,
      complete: false,
    });

    this.setState({
      textInput: '',
    })
  }
  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.title}>My Tasks</Text>
        <FlatList
          data={this.state.todos}
          renderItem={({ item }) => <Todo {...item} />}
          style={styles.flatList}
        />
        <View style={styles.viewInput}>
          <TextInput
            placeholder={'Add TODO'}
            value={this.state.textInput}
            onChangeText={(text) => this.updateTextInput(text)}
            style={styles.textInput}
          />
          <TouchableOpacity
            disabled={!this.state.textInput.length}
            onPress={() => this.addTodo()}
            style={styles.buttonAddNewTask}
          >
            <Text style={styles.titleButton}>Add new task</Text>
          </TouchableOpacity>
        </View>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#F5FCFF',
  },
  flatList: {
    margin: 10,
  },
  textInput: {
    height: 40
  },
  title: {
    marginTop: 50,
    fontWeight: '500',
    fontSize: 25,
    alignSelf: 'center',
  },
  viewInput: {
    shadowColor: 'black',
    shadowOffset: {
      width: 0,
      height: 3,
    },
    shadowRadius: 2,
    shadowOpacity: 0.2,
    marginTop: 10,
    borderTopWidth: 0.5,
    marginBottom: 20,
    paddingLeft: 10,
    paddingRight: 10
  },
  titleButton: {
    fontWeight: '500',
    fontSize: 20,
    color: 'white'
  },
  buttonAddNewTask: {
    backgroundColor: '#4286F3',
    height: 40,
    borderRadius: 20,
    justifyContent: 'center',
    alignItems: 'center',
    width: '80%',
    alignSelf: 'center',
    marginTop: 8
  }
});

Đây là một component điển hình trong React Native mà trước đó mình thường code. Nghĩa là thường để chung phần xử lý logic lấy data với phần render UI.
Cách viết như thế này sẽ có vấn đề sau:
– Thứ nhất: Với một màn hình thường sẽ có rất nhiều function để xử lý logic về dữ liệu và cả logic về UI. Với mình mình sẽ tách function rõ ràng nhất có thể nên có component mình viết rất nhiều function. Lấy ví dụ các Screen có nhiều TextInput các bạn sẽ có những function bắt sự kiện change text và cả validate nữa.
– Thứ hai: Viết như thế này chúng ta sẽ import tùm lum. Cái thì để gọi data, cái thì gọi các UI khác. Thử tưởng tượng thôi cũng thấy rối rồi. Lúc cần thì lại phải dò và mất 1 khoảng thời gian nghĩ xem đoạn nào import UI đoạn nào import logic

Đấy là hai vấn đề mình thường thấy.
Còn giờ mình sẽ nói về việc mình tách code:
Ý tưởng của mình là với mình màn hình có xử lý logic thì nên tách thành 2 files: index.js và render.js nó sẽ trông như thế này:

Đó các bạn thấy không.
Khi import component đó ở trỗ khác nó sẽ như thế này:

import ListTask from './ListTask'

và tự động nó sẽ nhảy vào file index.js

File index.js ban đầu nó sẽ trông như thế này:


import React, { Component } from 'react';
import firebase from 'react-native-firebase';
import { RenderListTask } from './render';

export default class ListTask extends Component {
  constructor(props) {
    super(props);
    this.ref = firebase.firestore().collection('todos');
    this.unsubcribe = null;
    this.state = {
      textInput: '',
      loading: true,
      todos: [],
    }
  }

  componentDidMount() {
    this.unsubcribe = this.ref.onSnapshot(this.onCollectionUpdate)
  }

  onCollectionUpdate = (querySnapshot) => {
    const todos = [];
    querySnapshot.forEach((doc) => {
      const { title, complete } = doc.data();
      todos.push({
        key: doc.id,
        doc,
        title,
        complete,
      })

      this.setState({
        todos,
        loading: false
      });
    });
  }

  componentWillUnmount() {
    this.unsubcribe();
  }

  updateTextInput(value) {
    this.setState({ textInput: value });
  }

  addTodo = () => {
    this.ref.add({
      title: this.state.textInput,
      complete: false,
    });

    this.setState({
      textInput: '',
    })
  }
  render() {
    const { todos, textInput} = this.state;
    return (
      <RenderListTask 
        todos={todos}
        textInput={textInput}
        updateTextInput={(text) =>this.updateTextInput(text)}
        addTodo={this.addTodo}      
      />
    );
  }
}

Và đây là render:


import React from 'react';
import {
    Platform,
    StyleSheet,
    Text,
    View,
    ScrollView,
    TextInput,
    TouchableOpacity,
    Alert,
    FlatList
} from 'react-native';
import Todo from '../../component/Todo';

export const RenderListTask = ({
    todos = [],
    textInput = '',
    updateTextInput = () => {},
    addTodo = () => {},

}) => {
    return (
        <View style={styles.container}>
            <Text style={styles.title}>My Tasks</Text>
            <FlatList
                data={todos}
                renderItem={({ item }) => <Todo {...item} />}
                style={styles.flatList}
            />
            <View style={styles.viewInput}>
                <TextInput
                    placeholder={'Add TODO'}
                    value={textInput}
                    onChangeText={(text) => updateTextInput(text)}
                    style={styles.textInput}
                />
                <TouchableOpacity
                    disabled={!textInput.length}
                    onPress={() => addTodo()}
                    style={styles.buttonAddNewTask}
                >
                    <Text style={styles.titleButton}>Add new task</Text>
                </TouchableOpacity>
            </View>
        </View>
    );
}

const styles = StyleSheet.create({
    container: {
      flex: 1,
      backgroundColor: '#F5FCFF',
    },
    flatList: {
      margin: 10,
    },
    textInput: {
      height: 40
    },
    title: {
      marginTop: 50,
      fontWeight: '500',
      fontSize: 25,
      alignSelf: 'center',
    },
    viewInput: {
      shadowColor: 'black',
      shadowOffset: {
        width: 0,
        height: 3,
      },
      shadowRadius: 2,
      shadowOpacity: 0.2,
      marginTop: 10,
      borderTopWidth: 0.5,
      marginBottom: 20,
      paddingLeft: 10,
      paddingRight: 10
    },
    titleButton: {
      fontWeight: '500',
      fontSize: 20,
      color: 'white'
    },
    buttonAddNewTask: {
      backgroundColor: '#4286F3',
      height: 40,
      borderRadius: 20,
      justifyContent: 'center',
      alignItems: 'center',
      width: '80%',
      alignSelf: 'center',
      marginTop: 8
    }
  });

Các bạn thấy khác biệt không:
– Đầu tiên là việc import:
+ Vì index.js chỉ xử lý các vấn đề về logic nên nó chỉ import các hàm cần thiết như firebase.
+ Còn render.js thì import các component.
– Thứ hai: Code rất tách biệt. Cần sửa code logic thì vào index. Sửa code UI thì vào render. Clear vãi lúa.
– Thứ ba: phần reder các bạn có thể default sẵn params.
– Thứ tư: Mình thật sự nghĩ việc gọi state hay props các bạn nên gọi 1 chỗ như thế này:


    const { todos, textInput} = this.state;
    const { props1, props2 } = this.props;

Nó sẽ không phải duplicate đoạn this.state hay this.props.
Và cũng nhìn kết quả nhé:

Đây là link github các bạn có thể clone về chạy thử:
Repo Demo

Vậy khi nào bạn nên viết như thế này:
– Khi nó là một Screen có xử lý nhiều logic. Các component nhỏ có thể không cần.
– Bạn muốn tách bạch code.
– Các dự án mới còn các dự án đang phát triển thì mình nghĩ không nên thay đổi code khi nó đang chạy ngon
Nếu bạn thấy bài viết hữu ích thì Like và Share nhé. Thank.

Series React Native Cơ Bản – Phần 3: Menu debug

Ở bài trước mình đã nói về cách cài đặt môi trường để code React Native bài này mình sẽ nói thêm 1 chút về một thứ rất hay ho: Menu debug
Vậy Menu Debug là gì?
– Nó là một Menu với danh sách các button bao gồm các chức năng:
+ Reload
+ Debug JS Remotely
+ Enable Live Reload/ Disable Enable Live Reload
+ Start Systrace
+ Enable Hot Reloading/Disable Hot Reloading
+ Toggle Inspector/
+ Show Perf Monitor/Hide Perf Monitor

Giờ chúng ta sẽ test thử nhé:
Đầu tiên tạo project:

react-native init AwesomeProject

Sau đó run project bằng lệnh:

react-native run-ios

or

react-native run-android

Khi project chạy xong để mở Menu chỉ cần dùng tổ hợp phím:
– Android: CMD + M
– iOS: CMD + D

Giờ chúng ta sẽ đi cụ thể vào từng chức năng:
Reload:
– Đơn giản là nó sẽ Reload lại project (Chạy app lại từ đầu).

Debug JS Remotely
– Bật Debug đồng thời nó sẽ open một trang local có dịa chỉ http://localhost:8081/debugger-ui/

– Cái này rất quan trọng và hay dùng nhất.
– Tại đây bạn có thể inpect ra và đọc log (Cái này mình sẽ nói sau)

Live Reload
– Việc bật Live Reload nó sẽ tự đông Reload lại project khi mà bạn thay đổi code và save lại. Bạn sẽ rảnh tay mà hơn so với việc cứ phải ấn CMD + R để Reload. Nhưng cẩn thận thế quen tay ấn save khi mà chưa code xong thì ăn ngay lỗi đỏ đó.

– Ở đây là mình dùng một thằng tên là Test (Đáng ra phải là Text) nhưng nó lại không tìm thấy thằng nào tên thế này cả.

Hot Reloading
– Hot Reloading hơi khác với Live Reload nó sẽ không Reload lại cả project mà nó sẽ render lại màn hình mà bạn đang bật. Nên thường sẽ không ai vừa bật cả Live Reload lẫn Hot Reload cả.

Toggle Inspector
– Nó sẽ bật debug UI trên chính device hoặc Simulator đang debug. Bạn có thể xem các thuộc tính trên đó. Cái này thường sẽ dùng với dev-tools(Mình sẽ hướng dẫn sau).

Perf Monitor
– Bật Perf Monitor sẽ có thể xem được các màn hình xem hiểu suất của ứng dụng.

Series React Native Cơ Bản – Phần 2: Cài đặt môi trường

Hiện tại React Native có thể code được trên nhiều hệ điều hành như Ubuntu, Window và tốt nhất là trên MacOS. Bởi vì chỉ trên MacOS chúng ta mới có thể build trên iOS được. Còn lại chỉ có thể code và build được trên Android nên để code React Native thì không thể thiếu MacOS.
Nên việc đầu tiên chính là mua Macbook nào bạn nào chưa có nhé 😀
Hoặc không thì các bạn có thể cài Hạckintosh nhưng lưu ý là nên có ram từ 8GB trở lên và sử dụng SSD là tốt nhất vì chúng ta phải chạy cả Simulator nữa.
Việc cài đặt môi trường mình nghĩ là quá dễ rồi các bạn chỉ cần flow theo hướng dẫn này là làm được hết thôi: Install React Native

Sau khi đã cài đặt xong bạn tạo project như sau:

react-native init project-sample

Chú ý nên viết liền project theo kiểu camel hoặc dấu ‘-‘ chứ không sử dụng dấu cách vì sẽ gây lỗi sau này.
Để chạy project thì chỉ cần chạy lệnh:
Chạy project iOS:

react-native run-ios


Chạy project Android:

react-native run-android

Lưu ý: Đối với iOS khi chạy project bạn không cần phải bật Simulator nó sẽ tự chạy cho bạn nhưng android thì bạn cần phải bật Simulator trước khi chạy lệnh run-android.


Lưu ý: Để code React Native ngoài cần cài đặt: NodeJS, react-native-cli, Android StudioXcode ra thì chúng ta cần có 1 Editor để code đúng không. Theo mình thì đa số developer code React Native sẽ chọn VSCode. Mình cũng không ngoại lệ. Nó cho phép mình cài rất nhiều extension trên đó để code. Nếu bạn chưa có thì có thể tải ở đây:
Link down VS Code

Load Test: Cài đặt Test Controller và Test Agents

Phần này mình sẽ hướng dẫn các bạn cách cài đặt Test Controller và Test agents

Giả dụ mình có các máy sau:
– Test controller: Ltcontroller(Tên máy)
– Test agents: Agent1, Agent2, Agent3 (Đây là tên các máy agent)
Bây giờ mình cần cài đặt Tools cho các máy:
1. Test controller:
B1. Bạn cần cài đặt Test Controller Configuration Tool cho test controller. Link download Test Controller Configuration Tools
Lưu ý: Bạn cần chọn Controller để download.
B2. Sau khi download và cài đặt xong bạn cần mở tools lên:
Chọn This Account và điền user và password vào. Lưu ý là tài khoản truy cập vào Ltcontroller với quyền admin nhé.

B3. Rồi chỉ cần Apply Settings là xong.
Để biết là service đã chạy chưa bạn cần mở Services trên windown lên và tìm Visual Studio Test Controller nếu nó đang chạy thì oke.
2. Test agents:
Tương tự controller bạn cũng cần cài tool cho từng máy agent. Bạn vào từng máy agent là tải Test Agent Configuration Tool về. Download tại đây Test Agent Configuration Tool
Bạn mở Configure Test Agent và chọn Service sau đó chọn Next
Trong Run test agent as a service, bàn cũng cần điền user và password cho nó. Lưu ý: đây cũng là tài khoản admin và cùng với tải khoản trên Test controller
Bên dưới chọn Register with Test controller: Giờ bạn điền tên máy là Test controller và cổng của nó:
Ví dụ: Ltcontroller.niteco.se:6901 (Cổng mặc định là 6901)
Chọn Apply Settings