Dirty push
This commit is contained in:
254
Cargo.lock
generated
Normal file
254
Cargo.lock
generated
Normal file
@@ -0,0 +1,254 @@
|
||||
[[package]]
|
||||
name = "adler32"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "bufstream"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "coco"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "color_quant"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "deflate"
|
||||
version = "0.7.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"adler32 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "enum_primitive"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fuchsia-zircon"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fuchsia-zircon-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fuchsia-zircon-sys"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "gif"
|
||||
version = "0.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"color_quant 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "image"
|
||||
version = "0.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gif 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"jpeg-decoder 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-iter 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-rational 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"png 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"scoped_threadpool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inflate"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"adler32 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jpeg-decoder"
|
||||
version = "0.1.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rayon 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "lzw"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-iter"
|
||||
version = "0.1.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-rational"
|
||||
version = "0.1.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.1.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pixelpwn"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"image 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "png"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"deflate 0.7.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"inflate 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-iter 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.3.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"fuchsia-zircon 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"rayon-core 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon-core"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"coco 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scoped_threadpool"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[metadata]
|
||||
"checksum adler32 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6cbd0b9af8587c72beadc9f72d35b9fbb070982c9e6203e46e93f10df25f8f45"
|
||||
"checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf"
|
||||
"checksum bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f382711e76b9de6c744cc00d0497baba02fb00a787f088c879f01d09468e32"
|
||||
"checksum byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "652805b7e73fada9d85e9a6682a4abd490cb52d96aeecc12e33a0de34dfd0d23"
|
||||
"checksum coco 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c06169f5beb7e31c7c67ebf5540b8b472d23e3eade3b2ec7d1f5b504a85f91bd"
|
||||
"checksum color_quant 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a475fc4af42d83d28adf72968d9bcfaf035a1a9381642d8e85d8a04957767b0d"
|
||||
"checksum deflate 0.7.17 (registry+https://github.com/rust-lang/crates.io-index)" = "4dddda59aaab719767ab11d3efd9a714e95b610c4445d4435765021e9d52dfb1"
|
||||
"checksum either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "740178ddf48b1a9e878e6d6509a1442a2d42fd2928aae8e7a6f8a36fb01981b3"
|
||||
"checksum enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be4551092f4d519593039259a9ed8daedf0da12e5109c5280338073eaeb81180"
|
||||
"checksum fuchsia-zircon 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bd510087c325af53ba24f3be8f1c081b0982319adcb8b03cad764512923ccc19"
|
||||
"checksum fuchsia-zircon-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "08b3a6f13ad6b96572b53ce7af74543132f1a7055ccceb6d073dd36c54481859"
|
||||
"checksum gif 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2e41945ba23db3bf51b24756d73d81acb4f28d85c3dccc32c6fae904438c25f"
|
||||
"checksum image 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "545f000e8aa4e569e93f49c446987133452e0091c2494ac3efd3606aa3d309f2"
|
||||
"checksum inflate 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "10ec05638adf7c5c788bc0cfa608cd479a13572beda20feb4898fe1d85d2c64b"
|
||||
"checksum jpeg-decoder 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2805ccb10ffe4d10e06ef68a158ff94c255211ecbae848fbde2146b098f93ce7"
|
||||
"checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73"
|
||||
"checksum libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)" = "36fbc8a8929c632868295d0178dd8f63fc423fd7537ad0738372bd010b3ac9b0"
|
||||
"checksum lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d947cbb889ed21c2a84be6ffbaebf5b4e0f4340638cba0444907e38b56be084"
|
||||
"checksum num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "d1452e8b06e448a07f0e6ebb0bb1d92b8890eea63288c0b627331d53514d0fba"
|
||||
"checksum num-iter 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)" = "7485fcc84f85b4ecd0ea527b14189281cf27d60e583ae65ebc9c088b13dffe01"
|
||||
"checksum num-rational 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "0c7cb72a95250d8a370105c828f388932373e0e94414919891a0f945222310fe"
|
||||
"checksum num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "cacfcab5eb48250ee7d0c7896b51a2c5eec99c1feea5f32025635f5ae4b00070"
|
||||
"checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30"
|
||||
"checksum png 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f0b0cabbbd20c2d7f06dbf015e06aad59b6ca3d9ed14848783e98af9aaf19925"
|
||||
"checksum rand 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)" = "9e7944d95d25ace8f377da3ac7068ce517e4c646754c43a1b1849177bbf72e59"
|
||||
"checksum rayon 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b614fe08b6665cb9a231d07ac1364b0ef3cb3698f1239ee0c4c3a88a524f54c8"
|
||||
"checksum rayon-core 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e64b609139d83da75902f88fd6c01820046840a18471e4dfcd5ac7c0f46bea53"
|
||||
"checksum scoped_threadpool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "4ea459fe3ceff01e09534847c49860891d3ff1c12b4eb7731b67f2778fb60190"
|
||||
"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
|
||||
@@ -4,4 +4,5 @@ version = "0.1.0"
|
||||
authors = ["Tim Visée <timvisee@gmail.com>"]
|
||||
|
||||
[dependencies]
|
||||
bufstream = "*"
|
||||
bufstream = "0.1"
|
||||
image = "0.18"
|
||||
|
||||
97
src/main.rs
97
src/main.rs
@@ -1,12 +1,17 @@
|
||||
extern crate bufstream;
|
||||
extern crate image;
|
||||
|
||||
use std::env;
|
||||
use std::fs::File;
|
||||
use std::io::Error;
|
||||
use std::io::prelude::*;
|
||||
use std::net::TcpStream;
|
||||
use std::path::Path;
|
||||
use std::thread;
|
||||
use std::thread::JoinHandle;
|
||||
|
||||
use bufstream::BufStream;
|
||||
use image::{GenericImage, DynamicImage, FilterType};
|
||||
|
||||
|
||||
|
||||
@@ -22,11 +27,16 @@ fn main() {
|
||||
// Start
|
||||
println!("Starting...");
|
||||
|
||||
// let range = Range::new(1, 1000);
|
||||
// let mut rng = rand::thread_rng();
|
||||
// Define the size to use
|
||||
// TODO: get the size from the screen
|
||||
let size = (1000u32, 1000u32);
|
||||
|
||||
// Define the image to use
|
||||
// TODO: get the image path from the CLI
|
||||
let image_path = "/home/timvisee/Pictures/sample.jpg";
|
||||
|
||||
// Create a new pixelflut canvas
|
||||
let canvas = PixCanvas::new(HOST, (1000, 1000), 10);
|
||||
let canvas = PixCanvas::new(HOST, image_path, size, 10);
|
||||
|
||||
loop {}
|
||||
}
|
||||
@@ -39,23 +49,47 @@ fn create_stream(host: String) -> Result<TcpStream, Error> {
|
||||
TcpStream::connect(host)
|
||||
}
|
||||
|
||||
/// Load the image at the given path, and size it correctly
|
||||
fn load_image(path: &str, size: &(u32, u32)) -> DynamicImage {
|
||||
// Create a path instance
|
||||
let path = Path::new(&path);
|
||||
|
||||
// TODO: make sure the path exists.
|
||||
|
||||
// Load the image
|
||||
println!("Loading image...");
|
||||
let image = image::open(&path).unwrap();
|
||||
|
||||
// Start processing the image for the screen
|
||||
println!("Processing image...");
|
||||
|
||||
// Resize the image to fit the screen
|
||||
image.resize_exact(
|
||||
size.0,
|
||||
size.1,
|
||||
FilterType::Gaussian,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// A pixflut instance
|
||||
struct PixCanvas {
|
||||
host: &'static str,
|
||||
size: (u16, u16),
|
||||
size: (u32, u32),
|
||||
painters: Vec<JoinHandle<u32>>,
|
||||
image: DynamicImage,
|
||||
}
|
||||
|
||||
impl PixCanvas {
|
||||
/// Create a new pixelflut canvas.
|
||||
pub fn new(host: &'static str, size: (u16, u16), painter_count: usize) -> PixCanvas {
|
||||
pub fn new(host: &'static str, image_path: &str, size: (u32, u32), painter_count: usize) -> PixCanvas {
|
||||
// Initialize the object
|
||||
let mut canvas = PixCanvas {
|
||||
host,
|
||||
size,
|
||||
painters: Vec::with_capacity(painter_count),
|
||||
image: load_image(image_path, &size),
|
||||
};
|
||||
|
||||
// Spawn some painters
|
||||
@@ -78,6 +112,14 @@ impl PixCanvas {
|
||||
// Get the host that will be used
|
||||
let host = self.host.to_string();
|
||||
|
||||
// Get the part of the image to draw by this painter
|
||||
let image = self.image.crop(
|
||||
area.x,
|
||||
area.y,
|
||||
area.w,
|
||||
area.h
|
||||
);
|
||||
|
||||
// Create the painter thread
|
||||
let thread = thread::spawn(move || {
|
||||
// Create a new stream
|
||||
@@ -88,7 +130,7 @@ impl PixCanvas {
|
||||
let client = PixClient::new(stream);
|
||||
|
||||
// Create a painter
|
||||
let mut painter = Painter::new(client, area);
|
||||
let mut painter = Painter::new(client, area, image);
|
||||
|
||||
// Do some work
|
||||
loop {
|
||||
@@ -106,27 +148,42 @@ impl PixCanvas {
|
||||
struct Painter {
|
||||
client: PixClient,
|
||||
area: Rect,
|
||||
image: DynamicImage,
|
||||
}
|
||||
|
||||
impl Painter {
|
||||
/// Create a new painter.
|
||||
pub fn new(client: PixClient, area: Rect) -> Painter {
|
||||
pub fn new(client: PixClient, area: Rect, image: DynamicImage) -> Painter {
|
||||
Painter {
|
||||
client,
|
||||
area,
|
||||
image,
|
||||
}
|
||||
}
|
||||
|
||||
/// Perform work.
|
||||
/// Paint the whole defined area.
|
||||
pub fn work(&mut self) {
|
||||
// Get an RGB image
|
||||
let image = self.image.to_rgb();
|
||||
|
||||
// Define the color to draw with
|
||||
let color = Color::from(0, 155, 0);
|
||||
|
||||
// Loop through all the pixels, and set their color
|
||||
for x in self.area.x..self.area.x + self.area.w {
|
||||
for y in self.area.y..self.area.y + self.area.h {
|
||||
self.client.write_pixel(x, y, &color);
|
||||
for x in 0..self.area.w {
|
||||
for y in 0..self.area.h {
|
||||
// Get the pixel at this location
|
||||
let pixel = image.get_pixel(x, y);
|
||||
|
||||
pixel.channels();
|
||||
|
||||
// Set the pixel
|
||||
self.client.write_pixel(
|
||||
x + self.area.x,
|
||||
y + self.area.y,
|
||||
&color,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -150,7 +207,7 @@ impl PixClient {
|
||||
}
|
||||
|
||||
/// Write a pixel to the given stream.
|
||||
fn write_pixel(&mut self, x: u16, y: u16, color: &Color) {
|
||||
fn write_pixel(&mut self, x: u32, y: u32, color: &Color) {
|
||||
// Write the command to set a pixel
|
||||
self.write_command(
|
||||
format!("PX {} {} {}", x, y, color.as_hex()),
|
||||
@@ -195,14 +252,14 @@ impl PixClient {
|
||||
/// Color structure.
|
||||
#[derive(Copy, Clone)]
|
||||
struct Color {
|
||||
r: u16,
|
||||
g: u16,
|
||||
b: u16,
|
||||
r: u32,
|
||||
g: u32,
|
||||
b: u32,
|
||||
}
|
||||
|
||||
impl Color {
|
||||
/// Create a new color instance
|
||||
pub fn from(r: u16, g: u16, b: u16) -> Color {
|
||||
pub fn from(r: u32, g: u32, b: u32) -> Color {
|
||||
Color {
|
||||
r,
|
||||
g,
|
||||
@@ -222,14 +279,14 @@ impl Color {
|
||||
/// Rectangle struct.
|
||||
pub struct Rect {
|
||||
// TODO: Make these properties private
|
||||
pub x: u16,
|
||||
pub y: u16,
|
||||
pub w: u16,
|
||||
pub h: u16,
|
||||
pub x: u32,
|
||||
pub y: u32,
|
||||
pub w: u32,
|
||||
pub h: u32,
|
||||
}
|
||||
|
||||
impl Rect {
|
||||
pub fn from(x: u16, y: u16, w: u16, h: u16) -> Rect {
|
||||
pub fn from(x: u32, y: u32, w: u32, h: u32) -> Rect {
|
||||
Rect {
|
||||
x,
|
||||
y,
|
||||
|
||||
Reference in New Issue
Block a user