From 07841bd2ec86cb667aea633de5dcb068751e64d3 Mon Sep 17 00:00:00 2001 From: Alex Auvolat Date: Mon, 15 Oct 2018 17:29:05 +0200 Subject: Friends list (beginning) --- shard/lib/app/directory.ex | 45 ++++++++++++++++++++++-- shardweb/lib/controllers/directory_controller.ex | 29 +++++++++++++++ shardweb/lib/controllers/identity_controller.ex | 34 ++++++++++++++++++ shardweb/lib/router.ex | 4 +++ shardweb/lib/templates/directory/view.html.eex | 38 ++++++++++++++++++++ shardweb/lib/templates/identity/view.html.eex | 12 +++++++ shardweb/lib/templates/layout/app.html.eex | 7 +++- shardweb/lib/templates/page/shard_entry.html.eex | 30 ++++++++++++++++ shardweb/lib/templates/page/shard_list.html.eex | 31 +--------------- shardweb/lib/views/directory_view.ex | 9 +++++ shardweb/lib/views/identity_view.ex | 5 +++ 11 files changed, 210 insertions(+), 34 deletions(-) create mode 100644 shardweb/lib/controllers/directory_controller.ex create mode 100644 shardweb/lib/templates/directory/view.html.eex create mode 100644 shardweb/lib/templates/page/shard_entry.html.eex create mode 100644 shardweb/lib/views/directory_view.ex diff --git a/shard/lib/app/directory.ex b/shard/lib/app/directory.ex index f7d871a..55413c4 100644 --- a/shard/lib/app/directory.ex +++ b/shard/lib/app/directory.ex @@ -42,10 +42,12 @@ defmodule SApp.Directory do end SNet.Group.init_lookup(netgroup, self()) + revfiles = for {n, m} <- SData.SignRev.get(files), into: %{}, do: {m, n} + {:ok, %{ owner: owner, public: public, name: name, manifest: manifest, id: id, netgroup: netgroup, - files: files}} + files: files, revfiles: revfiles}} end def handle_call(:manifest, _from, state) do @@ -66,7 +68,10 @@ defmodule SApp.Directory do GenServer.cast(Shard.Manager, {:dep_list, state.id, Map.values(dict)}) {:ok, st2} = SData.SignRev.set(state.files, dict, state.owner) Shard.Manager.save_state(state.id, st2) - state = put_in(state.files, st2) + state = %{state | + files: st2, + revfiles: Map.put(state.revfiles, manifest, name) + } bcast_state(state) {:reply, :ok, state} end @@ -81,6 +86,7 @@ defmodule SApp.Directory do if dict[name] == nil do {:reply, :not_found, state} else + state = put_in(state.revfiles, Map.delete(state.revfiles, dict[name])) dict = Map.delete(dict, name) GenServer.cast(Shard.Manager, {:dep_list, state.id, Map.values(dict)}) {:ok, st2} = SData.SignRev.set(state.files, dict, state.owner) @@ -94,6 +100,15 @@ defmodule SApp.Directory do end end + def handle_call({:read, name}, _from, state) do + dict = SData.SignRev.get(state.files) + {:reply, dict[name], state} + end + + def handle_call({:find, manifest}, _from, state) do + {:reply, state.revfiles[manifest], state} + end + def handle_cast(:send_deps, state) do dict = SData.SignRev.get(state.files) GenServer.cast(Shard.Manager, {:dep_list, state.id, Map.values(dict)}) @@ -144,12 +159,28 @@ defmodule SApp.Directory do @doc""" Return list of files stored in this directory. - Returns a list of {name, manifests}. + Returns a dictionnary of %{name => manifest}. """ def get_files(pid) do GenServer.call(pid, :get_files) end + @doc""" + Return the manifest of file with a given name in directory, or nil if not found. + + Equivalent to get_files(pid)[name] but better. + """ + def read(pid, name) do + GenServer.call(pid, {:read, name}) + end + + @doc""" + Find a file in the directory by its manifest. Returns name if found or nil if not found. + """ + def find(pid, manifest) do + GenServer.call(pid, {:find, manifest}) + end + @doc""" Add a file to this directory. A file is a name for a shard manifest. A file added to a directory becomes a dependency of the directory, i.e. @@ -165,4 +196,12 @@ defmodule SApp.Directory do def rm_file(pid, name) do GenServer.call(pid, {:rm_file, name}) end + + @doc""" + Returns the friends directory of a user + """ + def friends_dir(pk) do + manifest = %Manifest{name: "friends", owner: pk, public: false} + Shard.Manager.find_or_start manifest + end end diff --git a/shardweb/lib/controllers/directory_controller.ex b/shardweb/lib/controllers/directory_controller.ex new file mode 100644 index 0000000..1e3a0b0 --- /dev/null +++ b/shardweb/lib/controllers/directory_controller.ex @@ -0,0 +1,29 @@ +defmodule ShardWeb.DirectoryController do + use ShardWeb, :controller + + def view_pub(conn, %{"owner" => owner, "name" => name}) do + owner = Base.decode16! owner + shard = %SApp.Directory.Manifest{public: true, owner: owner, name: name} + pid = Shard.Manager.find_or_start shard + + render conn, "view.html", + public: true, + shard: shard, + pid: pid, + owner: owner, + name: name + end + + def view_priv(conn, %{"owner" => owner, "name" => name}) do + owner = Base.decode16! owner + shard = %SApp.Directory.Manifest{public: false, owner: owner, name: name} + pid = Shard.Manager.find_or_start shard + + render conn, "view.html", + public: false, + shard: shard, + pid: pid, + owner: owner, + name: name + end +end diff --git a/shardweb/lib/controllers/identity_controller.ex b/shardweb/lib/controllers/identity_controller.ex index 962a888..d1c6886 100644 --- a/shardweb/lib/controllers/identity_controller.ex +++ b/shardweb/lib/controllers/identity_controller.ex @@ -25,6 +25,40 @@ defmodule ShardWeb.IdentityController do end end + def view_post(conn, opts) do + IO.puts(inspect opts) + {:ok, pk} = Base.decode16(opts["pk"]) + manifest = %SApp.Identity.Manifest{pk: pk} + nick = SApp.Identity.get_nick pk + shard = manifest |> SData.term_hash + pid = Shard.Manager.find_proc shard + + if opts["add_friend"] == "true" do + friend_list = SApp.Directory.friends_dir(conn.assigns.pk) + name = nick <> " " <> Shard.Keys.pk_display(pk) + SApp.Directory.add_file(friend_list, name, manifest) + end + + if opts["rm_friend"] == "true" do + friend_list = SApp.Directory.friends_dir(conn.assigns.pk) + name = SApp.Directory.find(friend_list, manifest) + if name != nil do + SApp.Directory.rm_file(friend_list, name) + end + end + + if pid == nil do + render conn, ShardWeb.ErrorView, "404.html" + else + render conn, "view.html", + view_pk: pk, + view_nick: SApp.Identity.get_nick(pk), + shard: shard, + pid: pid + end + #TODO + end + def update(conn, params) do pid = SApp.Identity.find_proc(conn.assigns.pk) info = SApp.Identity.get_info(pid) diff --git a/shardweb/lib/router.ex b/shardweb/lib/router.ex index 981f946..eb1868f 100644 --- a/shardweb/lib/router.ex +++ b/shardweb/lib/router.ex @@ -24,11 +24,15 @@ defmodule ShardWeb.Router do get "/people", IdentityController, :list get "/people/:pk", IdentityController, :view + post "/people/:pk", IdentityController, :view_post get "/identity", IdentityController, :self post "/identity", IdentityController, :update post "/identity/switch", IdentityController, :switch post "/identity/create", IdentityController, :create + get "/pub/:owner/:name", DirectoryController, :view_pub + get "/priv/:owner/:name", DirectoryController, :view_priv + get "/chat/:chan", ChatController, :chat get "/pm/:people_list", ChatController, :privchat end diff --git a/shardweb/lib/templates/directory/view.html.eex b/shardweb/lib/templates/directory/view.html.eex new file mode 100644 index 0000000..b981391 --- /dev/null +++ b/shardweb/lib/templates/directory/view.html.eex @@ -0,0 +1,38 @@ + +
+
+

+ <%= @name %> + directory contents + +

+ +
+
+ + +<%= render ShardWeb.LayoutView, "flashes.html", assigns %> + + + + + + + + <%= for {name, manifest} <- dir_contents(@conn, @shard) do %> + + + + + + <% end %> +
NameShardId
+ <%= name %> + + <%= render ShardWeb.PageView, "shard_entry.html", conn: @conn, manifest: manifest %> + <%= (SData.term_hash manifest) |> Base.encode16 %>
+ diff --git a/shardweb/lib/templates/identity/view.html.eex b/shardweb/lib/templates/identity/view.html.eex index 58be7e7..6cb1bde 100644 --- a/shardweb/lib/templates/identity/view.html.eex +++ b/shardweb/lib/templates/identity/view.html.eex @@ -18,6 +18,18 @@ <%= render ShardWeb.LayoutView, "flashes.html", assigns %> +<%= if is_friend(@conn, @view_pk) do %> + <%= form_for @conn, identity_path(@conn, :view_post, @view_pk|>Base.encode16()), [class: "form-inline"], fn f -> %> + <%= hidden_input f, :rm_friend, value: "true" %> + <%= submit "Remove from friends", [class: "btn btn-sm btn-danger"] %> + <% end %> +<% else %> + <%= form_for @conn, identity_path(@conn, :view_post, @view_pk|>Base.encode16()), [class: "form-inline"], fn f -> %> + <%= hidden_input f, :add_friend, value: "true" %> + <%= submit "Add to friends", [class: "btn btn-sm btn-success"] %> + <% end %> +<% end %> +
   <%= inspect(SApp.Identity.get_info(@pid), pretty: true, width: 40) %>
 
diff --git a/shardweb/lib/templates/layout/app.html.eex b/shardweb/lib/templates/layout/app.html.eex index 8d9924e..71a08f9 100644 --- a/shardweb/lib/templates/layout/app.html.eex +++ b/shardweb/lib/templates/layout/app.html.eex @@ -150,8 +150,13 @@ + +
  • "> + "> Friends +
  • +
  • "> - People + Everyone <%= if (@view_module == ShardWeb.IdentityView and @view_template == "list.html") or (@view_module == ShardWeb.ChatView and @view_template == "chat.html" and not @public) do %>